summaryrefslogtreecommitdiffstats
path: root/src/backend/catalog
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/catalog')
-rw-r--r--src/backend/catalog/.gitignore4
-rw-r--r--src/backend/catalog/Catalog.pm540
-rw-r--r--src/backend/catalog/Makefile145
-rw-r--r--src/backend/catalog/aclchk.c6037
-rw-r--r--src/backend/catalog/bki-stamp0
-rw-r--r--src/backend/catalog/catalog.c533
-rw-r--r--src/backend/catalog/dependency.c2894
-rw-r--r--src/backend/catalog/genbki.pl977
-rw-r--r--src/backend/catalog/heap.c3826
-rw-r--r--src/backend/catalog/index.c4034
-rw-r--r--src/backend/catalog/indexing.c317
-rw-r--r--src/backend/catalog/information_schema.sql2937
-rw-r--r--src/backend/catalog/namespace.c4614
-rw-r--r--src/backend/catalog/objectaccess.c145
-rw-r--r--src/backend/catalog/objectaddress.c5378
-rw-r--r--src/backend/catalog/partition.c368
-rw-r--r--src/backend/catalog/pg_aggregate.c926
-rw-r--r--src/backend/catalog/pg_aggregate_d.h77
-rw-r--r--src/backend/catalog/pg_am_d.h45
-rw-r--r--src/backend/catalog/pg_amop_d.h41
-rw-r--r--src/backend/catalog/pg_amproc_d.h33
-rw-r--r--src/backend/catalog/pg_attrdef_d.h31
-rw-r--r--src/backend/catalog/pg_attribute_d.h59
-rw-r--r--src/backend/catalog/pg_auth_members_d.h32
-rw-r--r--src/backend/catalog/pg_authid_d.h49
-rw-r--r--src/backend/catalog/pg_cast.c123
-rw-r--r--src/backend/catalog/pg_cast_d.h62
-rw-r--r--src/backend/catalog/pg_class_d.h103
-rw-r--r--src/backend/catalog/pg_collation.c241
-rw-r--r--src/backend/catalog/pg_collation_d.h45
-rw-r--r--src/backend/catalog/pg_constraint.c1318
-rw-r--r--src/backend/catalog/pg_constraint_d.h67
-rw-r--r--src/backend/catalog/pg_conversion.c213
-rw-r--r--src/backend/catalog/pg_conversion_d.h35
-rw-r--r--src/backend/catalog/pg_database_d.h43
-rw-r--r--src/backend/catalog/pg_db_role_setting.c261
-rw-r--r--src/backend/catalog/pg_db_role_setting_d.h30
-rw-r--r--src/backend/catalog/pg_default_acl_d.h44
-rw-r--r--src/backend/catalog/pg_depend.c1068
-rw-r--r--src/backend/catalog/pg_depend_d.h34
-rw-r--r--src/backend/catalog/pg_description_d.h31
-rw-r--r--src/backend/catalog/pg_enum.c761
-rw-r--r--src/backend/catalog/pg_enum_d.h31
-rw-r--r--src/backend/catalog/pg_event_trigger_d.h34
-rw-r--r--src/backend/catalog/pg_extension_d.h35
-rw-r--r--src/backend/catalog/pg_foreign_data_wrapper_d.h34
-rw-r--r--src/backend/catalog/pg_foreign_server_d.h35
-rw-r--r--src/backend/catalog/pg_foreign_table_d.h30
-rw-r--r--src/backend/catalog/pg_index_d.h56
-rw-r--r--src/backend/catalog/pg_inherits.c493
-rw-r--r--src/backend/catalog/pg_inherits_d.h30
-rw-r--r--src/backend/catalog/pg_init_privs_d.h32
-rw-r--r--src/backend/catalog/pg_language_d.h39
-rw-r--r--src/backend/catalog/pg_largeobject.c187
-rw-r--r--src/backend/catalog/pg_largeobject_d.h30
-rw-r--r--src/backend/catalog/pg_largeobject_metadata_d.h30
-rw-r--r--src/backend/catalog/pg_namespace.c120
-rw-r--r--src/backend/catalog/pg_namespace_d.h34
-rw-r--r--src/backend/catalog/pg_opclass_d.h49
-rw-r--r--src/backend/catalog/pg_operator.c873
-rw-r--r--src/backend/catalog/pg_operator_d.h106
-rw-r--r--src/backend/catalog/pg_opfamily_d.h47
-rw-r--r--src/backend/catalog/pg_partitioned_table_d.h35
-rw-r--r--src/backend/catalog/pg_policy_d.h35
-rw-r--r--src/backend/catalog/pg_proc.c1157
-rw-r--r--src/backend/catalog/pg_proc_d.h99
-rw-r--r--src/backend/catalog/pg_publication.c557
-rw-r--r--src/backend/catalog/pg_publication_d.h36
-rw-r--r--src/backend/catalog/pg_publication_rel_d.h30
-rw-r--r--src/backend/catalog/pg_range.c137
-rw-r--r--src/backend/catalog/pg_range_d.h33
-rw-r--r--src/backend/catalog/pg_replication_origin_d.h29
-rw-r--r--src/backend/catalog/pg_rewrite_d.h35
-rw-r--r--src/backend/catalog/pg_seclabel_d.h32
-rw-r--r--src/backend/catalog/pg_sequence_d.h35
-rw-r--r--src/backend/catalog/pg_shdepend.c1618
-rw-r--r--src/backend/catalog/pg_shdepend_d.h34
-rw-r--r--src/backend/catalog/pg_shdescription_d.h30
-rw-r--r--src/backend/catalog/pg_shseclabel_d.h32
-rw-r--r--src/backend/catalog/pg_statistic_d.h194
-rw-r--r--src/backend/catalog/pg_statistic_ext_d.h40
-rw-r--r--src/backend/catalog/pg_statistic_ext_data_d.h31
-rw-r--r--src/backend/catalog/pg_subscription.c536
-rw-r--r--src/backend/catalog/pg_subscription_d.h37
-rw-r--r--src/backend/catalog/pg_subscription_rel_d.h48
-rw-r--r--src/backend/catalog/pg_tablespace_d.h34
-rw-r--r--src/backend/catalog/pg_transform_d.h32
-rw-r--r--src/backend/catalog/pg_trigger_d.h106
-rw-r--r--src/backend/catalog/pg_ts_config_d.h32
-rw-r--r--src/backend/catalog/pg_ts_config_map_d.h31
-rw-r--r--src/backend/catalog/pg_ts_dict_d.h33
-rw-r--r--src/backend/catalog/pg_ts_parser_d.h35
-rw-r--r--src/backend/catalog/pg_ts_template_d.h32
-rw-r--r--src/backend/catalog/pg_type.c906
-rw-r--r--src/backend/catalog/pg_type_d.h285
-rw-r--r--src/backend/catalog/pg_user_mapping_d.h31
-rw-r--r--src/backend/catalog/postgres.bki10432
-rw-r--r--src/backend/catalog/schemapg.h222
-rw-r--r--src/backend/catalog/sql_feature_packages.txt37
-rw-r--r--src/backend/catalog/sql_features.txt712
-rw-r--r--src/backend/catalog/storage.c1011
-rw-r--r--src/backend/catalog/system_views.sql1480
-rw-r--r--src/backend/catalog/toasting.c418
103 files changed, 61565 insertions, 0 deletions
diff --git a/src/backend/catalog/.gitignore b/src/backend/catalog/.gitignore
new file mode 100644
index 0000000..11e2e52
--- /dev/null
+++ b/src/backend/catalog/.gitignore
@@ -0,0 +1,4 @@
+/postgres.bki
+/schemapg.h
+/pg_*_d.h
+/bki-stamp
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
new file mode 100644
index 0000000..dd39a08
--- /dev/null
+++ b/src/backend/catalog/Catalog.pm
@@ -0,0 +1,540 @@
+#----------------------------------------------------------------------
+#
+# Catalog.pm
+# Perl module that extracts info from catalog files into Perl
+# data structures
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/backend/catalog/Catalog.pm
+#
+#----------------------------------------------------------------------
+
+package Catalog;
+
+use strict;
+use warnings;
+
+use File::Compare;
+
+
+# Parses a catalog header file into a data structure describing the schema
+# of the catalog.
+sub ParseHeader
+{
+ my $input_file = shift;
+
+ # 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 = (
+ 'int16' => 'int2',
+ 'int32' => 'int4',
+ 'int64' => 'int8',
+ 'Oid' => 'oid',
+ 'NameData' => 'name',
+ 'TransactionId' => 'xid',
+ 'XLogRecPtr' => 'pg_lsn');
+
+ my %catalog;
+ my $declaring_attributes = 0;
+ my $is_varlen = 0;
+ my $is_client_code = 0;
+
+ $catalog{columns} = [];
+ $catalog{toasting} = [];
+ $catalog{indexing} = [];
+ $catalog{client_code} = [];
+
+ open(my $ifh, '<', $input_file) || die "$input_file: $!";
+
+ # Scan the input file.
+ while (<$ifh>)
+ {
+
+ # Set appropriate flag when we're in certain code sections.
+ if (/^#/)
+ {
+ $is_varlen = 1 if /^#ifdef\s+CATALOG_VARLEN/;
+ if (/^#ifdef\s+EXPOSE_TO_CLIENT_CODE/)
+ {
+ $is_client_code = 1;
+ next;
+ }
+ next if !$is_client_code;
+ }
+
+ if (!$is_client_code)
+ {
+ # Strip C-style comments.
+ s;/\*(.|\n)*\*/;;g;
+ if (m;/\*;)
+ {
+
+ # handle multi-line comments properly.
+ my $next_line = <$ifh>;
+ 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.
+ # Caution: when adding new recognized OID-defining macros,
+ # also update src/include/catalog/renumber_oids.pl.
+ if (/^DECLARE_TOAST\(\s*(\w+),\s*(\d+),\s*(\d+)\)/)
+ {
+ push @{ $catalog{toasting} },
+ { parent_table => $1, toast_oid => $2, toast_index_oid => $3 };
+ }
+ elsif (/^DECLARE_(UNIQUE_)?INDEX\(\s*(\w+),\s*(\d+),\s*(.+)\)/)
+ {
+ push @{ $catalog{indexing} },
+ {
+ is_unique => $1 ? 1 : 0,
+ index_name => $2,
+ index_oid => $3,
+ index_decl => $4
+ };
+ }
+ elsif (/^CATALOG\((\w+),(\d+),(\w+)\)/)
+ {
+ $catalog{catname} = $1;
+ $catalog{relation_oid} = $2;
+ $catalog{relation_oid_macro} = $3;
+
+ $catalog{bootstrap} = /BKI_BOOTSTRAP/ ? ' bootstrap' : '';
+ $catalog{shared_relation} =
+ /BKI_SHARED_RELATION/ ? ' shared_relation' : '';
+ if (/BKI_ROWTYPE_OID\((\d+),(\w+)\)/)
+ {
+ $catalog{rowtype_oid} = $1;
+ $catalog{rowtype_oid_clause} = " rowtype_oid $1";
+ $catalog{rowtype_oid_macro} = $2;
+ }
+ else
+ {
+ $catalog{rowtype_oid} = '';
+ $catalog{rowtype_oid_clause} = '';
+ $catalog{rowtype_oid_macro} = '';
+ }
+ $catalog{schema_macro} = /BKI_SCHEMA_MACRO/ ? 1 : 0;
+ $declaring_attributes = 1;
+ }
+ elsif ($is_client_code)
+ {
+ if (/^#endif/)
+ {
+ $is_client_code = 0;
+ }
+ else
+ {
+ push @{ $catalog{client_code} }, $_;
+ }
+ }
+ elsif ($declaring_attributes)
+ {
+ next if (/^{|^$/);
+ if (/^}/)
+ {
+ $declaring_attributes = 0;
+ }
+ else
+ {
+ my %column;
+ my @attopts = split /\s+/, $_;
+ my $atttype = shift @attopts;
+ my $attname = shift @attopts;
+ die "parse error ($input_file)"
+ unless ($attname and $atttype);
+
+ if (exists $RENAME_ATTTYPE{$atttype})
+ {
+ $atttype = $RENAME_ATTTYPE{$atttype};
+ }
+
+ # If the C name ends with '[]' or '[digits]', we have
+ # an array type, so we discard that from the name and
+ # prepend '_' to the type.
+ if ($attname =~ /(\w+)\[\d*\]/)
+ {
+ $attname = $1;
+ $atttype = '_' . $atttype;
+ }
+
+ $column{type} = $atttype;
+ $column{name} = $attname;
+ $column{is_varlen} = 1 if $is_varlen;
+
+ foreach my $attopt (@attopts)
+ {
+ if ($attopt eq 'BKI_FORCE_NULL')
+ {
+ $column{forcenull} = 1;
+ }
+ elsif ($attopt eq 'BKI_FORCE_NOT_NULL')
+ {
+ $column{forcenotnull} = 1;
+ }
+
+ # We use quotes for values like \0 and \054, to
+ # make sure all compilers and syntax highlighters
+ # can recognize them properly.
+ elsif ($attopt =~ /BKI_DEFAULT\(['"]?([^'"]+)['"]?\)/)
+ {
+ $column{default} = $1;
+ }
+ elsif (
+ $attopt =~ /BKI_ARRAY_DEFAULT\(['"]?([^'"]+)['"]?\)/)
+ {
+ $column{array_default} = $1;
+ }
+ elsif ($attopt =~ /BKI_LOOKUP\((\w+)\)/)
+ {
+ $column{lookup} = $1;
+ }
+ else
+ {
+ die
+ "unknown or misformatted column option $attopt on column $attname";
+ }
+
+ if ($column{forcenull} and $column{forcenotnull})
+ {
+ die "$attname is forced both null and not null";
+ }
+ }
+ push @{ $catalog{columns} }, \%column;
+ }
+ }
+ }
+ close $ifh;
+ return \%catalog;
+}
+
+# Parses a file containing Perl data structure literals, returning live data.
+#
+# The parameter $preserve_formatting needs to be set for callers that want
+# to work with non-data lines in the data files, such as comments and blank
+# lines. If a caller just wants to consume the data, leave it unset.
+sub ParseData
+{
+ my ($input_file, $schema, $preserve_formatting) = @_;
+
+ open(my $ifd, '<', $input_file) || die "$input_file: $!";
+ $input_file =~ /(\w+)\.dat$/
+ or die "Input file $input_file needs to be a .dat file.\n";
+ my $catname = $1;
+ my $data = [];
+
+ # Scan the input file.
+ while (<$ifd>)
+ {
+ my $hash_ref;
+
+ if (/{/)
+ {
+ # Capture the hash ref
+ # NB: Assumes that the next hash ref can't start on the
+ # same line where the present one ended.
+ # Not foolproof, but we shouldn't need a full parser,
+ # since we expect relatively well-behaved input.
+
+ # Quick hack to detect when we have a full hash ref to
+ # parse. We can't just use a regex because of values in
+ # pg_aggregate and pg_proc like '{0,0}'. This will need
+ # work if we ever need to allow unbalanced braces within
+ # a field value.
+ my $lcnt = tr/{//;
+ my $rcnt = tr/}//;
+
+ if ($lcnt == $rcnt)
+ {
+ # We're treating the input line as a piece of Perl, so we
+ # need to use string eval here. Tell perlcritic we know what
+ # we're doing.
+ eval '$hash_ref = ' . $_; ## no critic (ProhibitStringyEval)
+ if (!ref $hash_ref)
+ {
+ die "$input_file: error parsing line $.:\n$_\n";
+ }
+
+ # Annotate each hash with the source line number.
+ $hash_ref->{line_number} = $.;
+
+ # Expand tuples to their full representation.
+ AddDefaultValues($hash_ref, $schema, $catname);
+ }
+ else
+ {
+ my $next_line = <$ifd>;
+ die "$input_file: file ends within Perl hash\n"
+ if !defined $next_line;
+ $_ .= $next_line;
+ redo;
+ }
+ }
+
+ # 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 if !$hash_ref->{autogenerated};
+ }
+ elsif ($preserve_formatting)
+ {
+ push @$data, $_;
+ }
+ }
+ close $ifd;
+
+ # If this is pg_type, auto-generate array types too.
+ GenerateArrayTypes($schema, $data) if $catname eq 'pg_type';
+
+ return $data;
+}
+
+# Fill in default values of a record using the given schema.
+# It's the caller's responsibility to specify other values beforehand.
+sub AddDefaultValues
+{
+ my ($row, $schema, $catname) = @_;
+ my @missing_fields;
+
+ # Compute special-case column values.
+ # Note: If you add new cases here, you must also teach
+ # strip_default_values() in include/catalog/reformat_dat_file.pl
+ # to delete them.
+ if ($catname eq 'pg_proc')
+ {
+ # pg_proc.pronargs can be derived from proargtypes.
+ if (defined $row->{proargtypes})
+ {
+ my @proargtypes = split /\s+/, $row->{proargtypes};
+ $row->{pronargs} = scalar(@proargtypes);
+ }
+ }
+
+ # Now fill in defaults, and note any columns that remain undefined.
+ foreach my $column (@$schema)
+ {
+ my $attname = $column->{name};
+
+ # No work if field already has a value.
+ next if defined $row->{$attname};
+
+ # Ignore 'oid' columns, they're handled elsewhere.
+ next if $attname eq 'oid';
+
+ # If column has a default value, fill that in.
+ if (defined $column->{default})
+ {
+ $row->{$attname} = $column->{default};
+ next;
+ }
+
+ # Failed to find a value for this field.
+ push @missing_fields, $attname;
+ }
+
+ # Failure to provide all columns is a hard error.
+ if (@missing_fields)
+ {
+ die sprintf "missing values for field(s) %s in %s.dat line %s\n",
+ join(', ', @missing_fields), $catname, $row->{line_number};
+ }
+}
+
+# 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;
+
+ return;
+}
+
+# Rename temporary files to final names.
+# Call this function with the final file name and the .tmp extension.
+#
+# If the final file already exists and has identical contents, don't
+# overwrite it; this behavior avoids unnecessary recompiles due to
+# updating the mod date on unchanged header files.
+#
+# Note: recommended extension is ".tmp$$", so that parallel make steps
+# can't use the same temp files.
+sub RenameTempFile
+{
+ my $final_name = shift;
+ my $extension = shift;
+ my $temp_name = $final_name . $extension;
+
+ if (-f $final_name
+ && compare($temp_name, $final_name) == 0)
+ {
+ unlink($temp_name) || die "unlink: $temp_name: $!";
+ }
+ else
+ {
+ rename($temp_name, $final_name) || die "rename: $temp_name: $!";
+ }
+ return;
+}
+
+# Find a symbol defined in a particular header file and extract the value.
+# include_path should be the path to src/include/.
+sub FindDefinedSymbol
+{
+ my ($catalog_header, $include_path, $symbol) = @_;
+ my $value;
+
+ # Make sure include path ends in a slash.
+ if (substr($include_path, -1) ne '/')
+ {
+ $include_path .= '/';
+ }
+ my $file = $include_path . $catalog_header;
+ open(my $find_defined_symbol, '<', $file) || die "$file: $!";
+ while (<$find_defined_symbol>)
+ {
+ if (/^#define\s+\Q$symbol\E\s+(\S+)/)
+ {
+ $value = $1;
+ last;
+ }
+ }
+ close $find_defined_symbol;
+ return $value if defined $value;
+ die "$file: no definition found for $symbol\n";
+}
+
+# Similar to FindDefinedSymbol, but looks in the bootstrap metadata.
+sub FindDefinedSymbolFromData
+{
+ my ($data, $symbol) = @_;
+ foreach my $row (@{$data})
+ {
+ if ($row->{oid_symbol} eq $symbol)
+ {
+ return $row->{oid};
+ }
+ }
+ die "no definition found for $symbol\n";
+}
+
+# Extract an array of all the OIDs assigned in the specified catalog headers
+# and their associated data files (if any).
+# Caution: genbki.pl contains equivalent logic; change it too if you need to
+# touch this.
+sub FindAllOidsFromHeaders
+{
+ my @input_files = @_;
+
+ my @oids = ();
+
+ foreach my $header (@input_files)
+ {
+ $header =~ /(.+)\.h$/
+ or die "Input files need to be header files.\n";
+ my $datfile = "$1.dat";
+
+ my $catalog = Catalog::ParseHeader($header);
+
+ # We ignore the pg_class OID and rowtype OID of bootstrap catalogs,
+ # as those are expected to appear in the initial data for pg_class
+ # and pg_type. For regular catalogs, include these OIDs.
+ if (!$catalog->{bootstrap})
+ {
+ push @oids, $catalog->{relation_oid}
+ if ($catalog->{relation_oid});
+ push @oids, $catalog->{rowtype_oid} if ($catalog->{rowtype_oid});
+ }
+
+ # Not all catalogs have a data file.
+ if (-e $datfile)
+ {
+ my $catdata =
+ Catalog::ParseData($datfile, $catalog->{columns}, 0);
+
+ foreach my $row (@$catdata)
+ {
+ push @oids, $row->{oid} if defined $row->{oid};
+ }
+ }
+
+ foreach my $toast (@{ $catalog->{toasting} })
+ {
+ push @oids, $toast->{toast_oid}, $toast->{toast_index_oid};
+ }
+ foreach my $index (@{ $catalog->{indexing} })
+ {
+ push @oids, $index->{index_oid};
+ }
+ }
+
+ return \@oids;
+}
+
+1;
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
new file mode 100644
index 0000000..9499bb3
--- /dev/null
+++ b/src/backend/catalog/Makefile
@@ -0,0 +1,145 @@
+#-------------------------------------------------------------------------
+#
+# Makefile for backend/catalog
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/backend/catalog/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/backend/catalog
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = \
+ aclchk.o \
+ catalog.o \
+ dependency.o \
+ heap.o \
+ index.o \
+ indexing.o \
+ namespace.o \
+ objectaccess.o \
+ objectaddress.o \
+ partition.o \
+ pg_aggregate.o \
+ pg_cast.o \
+ pg_collation.o \
+ pg_constraint.o \
+ pg_conversion.o \
+ pg_db_role_setting.o \
+ pg_depend.o \
+ pg_enum.o \
+ pg_inherits.o \
+ pg_largeobject.o \
+ pg_namespace.o \
+ pg_operator.o \
+ pg_proc.o \
+ pg_publication.o \
+ pg_range.o \
+ pg_shdepend.o \
+ pg_subscription.o \
+ pg_type.o \
+ storage.o \
+ toasting.o
+
+include $(top_srcdir)/src/backend/common.mk
+
+# Note: the order of this list determines the order in which the catalog
+# header files are assembled into postgres.bki. BKI_BOOTSTRAP catalogs
+# must appear first, and there are reputedly other, undocumented ordering
+# dependencies.
+CATALOG_HEADERS := \
+ pg_proc.h pg_type.h pg_attribute.h pg_class.h \
+ pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h pg_operator.h \
+ pg_opfamily.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
+ pg_language.h pg_largeobject_metadata.h pg_largeobject.h pg_aggregate.h \
+ pg_statistic_ext.h pg_statistic_ext_data.h \
+ pg_statistic.h pg_rewrite.h pg_trigger.h pg_event_trigger.h pg_description.h \
+ pg_cast.h pg_enum.h pg_namespace.h pg_conversion.h pg_depend.h \
+ pg_database.h pg_db_role_setting.h pg_tablespace.h \
+ pg_authid.h pg_auth_members.h pg_shdepend.h pg_shdescription.h \
+ pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \
+ pg_ts_parser.h pg_ts_template.h pg_extension.h \
+ pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
+ pg_foreign_table.h pg_policy.h pg_replication_origin.h \
+ pg_default_acl.h pg_init_privs.h pg_seclabel.h pg_shseclabel.h \
+ pg_collation.h pg_partitioned_table.h pg_range.h pg_transform.h \
+ pg_sequence.h pg_publication.h pg_publication_rel.h pg_subscription.h \
+ pg_subscription_rel.h
+
+GENERATED_HEADERS := $(CATALOG_HEADERS:%.h=%_d.h) schemapg.h
+
+# In the list of headers used to assemble postgres.bki, indexing.h needs
+# be last, and toasting.h just before it. This ensures we don't try to
+# create indexes or toast tables before their catalogs exist.
+POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
+ $(CATALOG_HEADERS) toasting.h indexing.h \
+ )
+
+# The .dat files we need can just be listed alphabetically.
+POSTGRES_BKI_DATA = $(addprefix $(top_srcdir)/src/include/catalog/,\
+ pg_aggregate.dat pg_am.dat pg_amop.dat pg_amproc.dat pg_authid.dat \
+ pg_cast.dat pg_class.dat pg_collation.dat pg_conversion.dat \
+ pg_database.dat pg_language.dat \
+ pg_namespace.dat pg_opclass.dat pg_operator.dat pg_opfamily.dat \
+ pg_proc.dat pg_range.dat pg_tablespace.dat \
+ pg_ts_config.dat pg_ts_config_map.dat pg_ts_dict.dat pg_ts_parser.dat \
+ pg_ts_template.dat pg_type.dat \
+ )
+
+all: distprep generated-header-symlinks
+
+distprep: bki-stamp
+
+.PHONY: generated-header-symlinks
+
+generated-header-symlinks: $(top_builddir)/src/include/catalog/header-stamp
+
+# bki-stamp records the last time we ran genbki.pl. We don't rely on
+# the timestamps of the individual output files, because the Perl script
+# won't update them if they didn't change (to avoid unnecessary recompiles).
+# Technically, this should depend on Makefile.global which supplies
+# $(MAJORVERSION); but then genbki.pl would need to be re-run after every
+# configure run, even in distribution tarballs. So depending on configure.in
+# instead is cheating a bit, but it will achieve the goal of updating the
+# version number when it changes.
+bki-stamp: genbki.pl Catalog.pm $(POSTGRES_BKI_SRCS) $(POSTGRES_BKI_DATA) $(top_srcdir)/configure.in
+ $(PERL) $< --include-path=$(top_srcdir)/src/include/ \
+ --set-version=$(MAJORVERSION) $(POSTGRES_BKI_SRCS)
+ touch $@
+
+# The generated headers must all be symlinked into builddir/src/include/,
+# using absolute links for the reasons explained in src/backend/Makefile.
+# We use header-stamp to record that we've done this because the symlinks
+# themselves may appear older than bki-stamp.
+$(top_builddir)/src/include/catalog/header-stamp: bki-stamp
+ prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
+ cd '$(dir $@)' && for file in $(GENERATED_HEADERS); do \
+ rm -f $$file && $(LN_S) "$$prereqdir/$$file" . ; \
+ done
+ touch $@
+
+# Note: installation of generated headers is handled elsewhere
+.PHONY: install-data
+install-data: bki-stamp installdirs
+ $(INSTALL_DATA) $(call vpathsearch,postgres.bki) '$(DESTDIR)$(datadir)/postgres.bki'
+ $(INSTALL_DATA) $(srcdir)/system_views.sql '$(DESTDIR)$(datadir)/system_views.sql'
+ $(INSTALL_DATA) $(srcdir)/information_schema.sql '$(DESTDIR)$(datadir)/information_schema.sql'
+ $(INSTALL_DATA) $(srcdir)/sql_features.txt '$(DESTDIR)$(datadir)/sql_features.txt'
+
+installdirs:
+ $(MKDIR_P) '$(DESTDIR)$(datadir)'
+
+.PHONY: uninstall-data
+uninstall-data:
+ rm -f $(addprefix '$(DESTDIR)$(datadir)'/, postgres.bki system_views.sql information_schema.sql sql_features.txt)
+
+# postgres.bki and the generated headers are in the distribution tarball,
+# so they are not cleaned here.
+clean:
+
+maintainer-clean: clean
+ rm -f bki-stamp postgres.bki $(GENERATED_HEADERS)
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
new file mode 100644
index 0000000..4f1e8a4
--- /dev/null
+++ b/src/backend/catalog/aclchk.c
@@ -0,0 +1,6037 @@
+/*-------------------------------------------------------------------------
+ *
+ * aclchk.c
+ * Routines to check access control permissions.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/aclchk.c
+ *
+ * NOTES
+ * See acl.h.
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/tableam.h"
+#include "access/xact.h"
+#include "catalog/binary_upgrade.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_cast.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_conversion.h"
+#include "catalog/pg_database.h"
+#include "catalog/pg_default_acl.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_init_privs.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_proc.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_ts_config.h"
+#include "catalog/pg_ts_dict.h"
+#include "catalog/pg_ts_parser.h"
+#include "catalog/pg_ts_template.h"
+#include "catalog/pg_type.h"
+#include "commands/dbcommands.h"
+#include "commands/event_trigger.h"
+#include "commands/extension.h"
+#include "commands/proclang.h"
+#include "commands/tablespace.h"
+#include "foreign/foreign.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "parser/parse_func.h"
+#include "parser/parse_type.h"
+#include "utils/acl.h"
+#include "utils/aclchk_internal.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+/*
+ * Internal format used by ALTER DEFAULT PRIVILEGES.
+ */
+typedef struct
+{
+ Oid roleid; /* owning role */
+ Oid nspid; /* namespace, or InvalidOid if none */
+ /* remaining fields are same as in InternalGrant: */
+ bool is_grant;
+ ObjectType objtype;
+ bool all_privs;
+ AclMode privileges;
+ List *grantees;
+ bool grant_option;
+ DropBehavior behavior;
+} InternalDefaultACL;
+
+/*
+ * When performing a binary-upgrade, pg_dump will call a function to set
+ * this variable to let us know that we need to populate the pg_init_privs
+ * table for the GRANT/REVOKE commands while this variable is set to true.
+ */
+bool binary_upgrade_record_init_privs = false;
+
+static void ExecGrantStmt_oids(InternalGrant *istmt);
+static void ExecGrant_Relation(InternalGrant *grantStmt);
+static void ExecGrant_Database(InternalGrant *grantStmt);
+static void ExecGrant_Fdw(InternalGrant *grantStmt);
+static void ExecGrant_ForeignServer(InternalGrant *grantStmt);
+static void ExecGrant_Function(InternalGrant *grantStmt);
+static void ExecGrant_Language(InternalGrant *grantStmt);
+static void ExecGrant_Largeobject(InternalGrant *grantStmt);
+static void ExecGrant_Namespace(InternalGrant *grantStmt);
+static void ExecGrant_Tablespace(InternalGrant *grantStmt);
+static void ExecGrant_Type(InternalGrant *grantStmt);
+
+static void SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames);
+static void SetDefaultACL(InternalDefaultACL *iacls);
+
+static List *objectNamesToOids(ObjectType objtype, List *objnames);
+static List *objectsInSchemaToOids(ObjectType objtype, List *nspnames);
+static List *getRelationsInNamespace(Oid namespaceId, char relkind);
+static void expand_col_privileges(List *colnames, Oid table_oid,
+ AclMode this_privileges,
+ AclMode *col_privileges,
+ int num_col_privileges);
+static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
+ AclMode this_privileges,
+ AclMode *col_privileges,
+ int num_col_privileges);
+static AclMode string_to_privilege(const char *privname);
+static const char *privilege_to_string(AclMode privilege);
+static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
+ bool all_privs, AclMode privileges,
+ Oid objectId, Oid grantorId,
+ ObjectType objtype, const char *objname,
+ AttrNumber att_number, const char *colname);
+static AclMode pg_aclmask(ObjectType objtype, Oid table_oid, AttrNumber attnum,
+ Oid roleid, AclMode mask, AclMaskHow how);
+static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
+ Acl *new_acl);
+static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
+ Acl *new_acl);
+
+
+/*
+ * If is_grant is true, adds the given privileges for the list of
+ * grantees to the existing old_acl. If is_grant is false, the
+ * privileges for the given grantees are removed from old_acl.
+ *
+ * NB: the original old_acl is pfree'd.
+ */
+static Acl *
+merge_acl_with_grant(Acl *old_acl, bool is_grant,
+ bool grant_option, DropBehavior behavior,
+ List *grantees, AclMode privileges,
+ Oid grantorId, Oid ownerId)
+{
+ unsigned modechg;
+ ListCell *j;
+ Acl *new_acl;
+
+ modechg = is_grant ? ACL_MODECHG_ADD : ACL_MODECHG_DEL;
+
+ new_acl = old_acl;
+
+ foreach(j, grantees)
+ {
+ AclItem aclitem;
+ Acl *newer_acl;
+
+ aclitem.ai_grantee = lfirst_oid(j);
+
+ /*
+ * Grant options can only be granted to individual roles, not PUBLIC.
+ * The reason is that if a user would re-grant a privilege that he
+ * held through PUBLIC, and later the user is removed, the situation
+ * is impossible to clean up.
+ */
+ if (is_grant && grant_option && aclitem.ai_grantee == ACL_ID_PUBLIC)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("grant options can only be granted to roles")));
+
+ aclitem.ai_grantor = grantorId;
+
+ /*
+ * The asymmetry in the conditions here comes from the spec. In
+ * GRANT, the grant_option flag signals WITH GRANT OPTION, which means
+ * to grant both the basic privilege and its grant option. But in
+ * REVOKE, plain revoke revokes both the basic privilege and its grant
+ * option, while REVOKE GRANT OPTION revokes only the option.
+ */
+ ACLITEM_SET_PRIVS_GOPTIONS(aclitem,
+ (is_grant || !grant_option) ? privileges : ACL_NO_RIGHTS,
+ (!is_grant || grant_option) ? privileges : ACL_NO_RIGHTS);
+
+ newer_acl = aclupdate(new_acl, &aclitem, modechg, ownerId, behavior);
+
+ /* avoid memory leak when there are many grantees */
+ pfree(new_acl);
+ new_acl = newer_acl;
+ }
+
+ return new_acl;
+}
+
+/*
+ * Restrict the privileges to what we can actually grant, and emit
+ * the standards-mandated warning and error messages.
+ */
+static AclMode
+restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
+ AclMode privileges, Oid objectId, Oid grantorId,
+ ObjectType objtype, const char *objname,
+ AttrNumber att_number, const char *colname)
+{
+ AclMode this_privileges;
+ AclMode whole_mask;
+
+ switch (objtype)
+ {
+ case OBJECT_COLUMN:
+ whole_mask = ACL_ALL_RIGHTS_COLUMN;
+ break;
+ case OBJECT_TABLE:
+ whole_mask = ACL_ALL_RIGHTS_RELATION;
+ break;
+ case OBJECT_SEQUENCE:
+ whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
+ break;
+ case OBJECT_DATABASE:
+ whole_mask = ACL_ALL_RIGHTS_DATABASE;
+ break;
+ case OBJECT_FUNCTION:
+ whole_mask = ACL_ALL_RIGHTS_FUNCTION;
+ break;
+ case OBJECT_LANGUAGE:
+ whole_mask = ACL_ALL_RIGHTS_LANGUAGE;
+ break;
+ case OBJECT_LARGEOBJECT:
+ whole_mask = ACL_ALL_RIGHTS_LARGEOBJECT;
+ break;
+ case OBJECT_SCHEMA:
+ whole_mask = ACL_ALL_RIGHTS_SCHEMA;
+ break;
+ case OBJECT_TABLESPACE:
+ whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
+ break;
+ case OBJECT_FDW:
+ whole_mask = ACL_ALL_RIGHTS_FDW;
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ elog(ERROR, "grantable rights not supported for event triggers");
+ /* not reached, but keep compiler quiet */
+ return ACL_NO_RIGHTS;
+ case OBJECT_TYPE:
+ whole_mask = ACL_ALL_RIGHTS_TYPE;
+ break;
+ default:
+ elog(ERROR, "unrecognized object type: %d", objtype);
+ /* not reached, but keep compiler quiet */
+ return ACL_NO_RIGHTS;
+ }
+
+ /*
+ * If we found no grant options, consider whether to issue a hard error.
+ * Per spec, having any privilege at all on the object will get you by
+ * here.
+ */
+ if (avail_goptions == ACL_NO_RIGHTS)
+ {
+ if (pg_aclmask(objtype, objectId, att_number, grantorId,
+ whole_mask | ACL_GRANT_OPTION_FOR(whole_mask),
+ ACLMASK_ANY) == ACL_NO_RIGHTS)
+ {
+ if (objtype == OBJECT_COLUMN && colname)
+ aclcheck_error_col(ACLCHECK_NO_PRIV, objtype, objname, colname);
+ else
+ aclcheck_error(ACLCHECK_NO_PRIV, objtype, objname);
+ }
+ }
+
+ /*
+ * Restrict the operation to what we can actually grant or revoke, and
+ * issue a warning if appropriate. (For REVOKE this isn't quite what the
+ * spec says to do: the spec seems to want a warning only if no privilege
+ * bits actually change in the ACL. In practice that behavior seems much
+ * too noisy, as well as inconsistent with the GRANT case.)
+ */
+ this_privileges = privileges & ACL_OPTION_TO_PRIVS(avail_goptions);
+ if (is_grant)
+ {
+ if (this_privileges == 0)
+ {
+ if (objtype == OBJECT_COLUMN && colname)
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
+ errmsg("no privileges were granted for column \"%s\" of relation \"%s\"",
+ colname, objname)));
+ else
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
+ errmsg("no privileges were granted for \"%s\"",
+ objname)));
+ }
+ else if (!all_privs && this_privileges != privileges)
+ {
+ if (objtype == OBJECT_COLUMN && colname)
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
+ errmsg("not all privileges were granted for column \"%s\" of relation \"%s\"",
+ colname, objname)));
+ else
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
+ errmsg("not all privileges were granted for \"%s\"",
+ objname)));
+ }
+ }
+ else
+ {
+ if (this_privileges == 0)
+ {
+ if (objtype == OBJECT_COLUMN && colname)
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
+ errmsg("no privileges could be revoked for column \"%s\" of relation \"%s\"",
+ colname, objname)));
+ else
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
+ errmsg("no privileges could be revoked for \"%s\"",
+ objname)));
+ }
+ else if (!all_privs && this_privileges != privileges)
+ {
+ if (objtype == OBJECT_COLUMN && colname)
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
+ errmsg("not all privileges could be revoked for column \"%s\" of relation \"%s\"",
+ colname, objname)));
+ else
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
+ errmsg("not all privileges could be revoked for \"%s\"",
+ objname)));
+ }
+ }
+
+ return this_privileges;
+}
+
+/*
+ * Called to execute the utility commands GRANT and REVOKE
+ */
+void
+ExecuteGrantStmt(GrantStmt *stmt)
+{
+ InternalGrant istmt;
+ ListCell *cell;
+ const char *errormsg;
+ AclMode all_privileges;
+
+ /*
+ * Turn the regular GrantStmt into the InternalGrant form.
+ */
+ istmt.is_grant = stmt->is_grant;
+ istmt.objtype = stmt->objtype;
+
+ /* Collect the OIDs of the target objects */
+ switch (stmt->targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
+ break;
+ /* ACL_TARGET_DEFAULTS should not be seen here */
+ default:
+ elog(ERROR, "unrecognized GrantStmt.targtype: %d",
+ (int) stmt->targtype);
+ }
+
+ /* all_privs to be filled below */
+ /* privileges to be filled below */
+ istmt.col_privs = NIL; /* may get filled below */
+ istmt.grantees = NIL; /* filled below */
+ istmt.grant_option = stmt->grant_option;
+ istmt.behavior = stmt->behavior;
+
+ /*
+ * Convert the RoleSpec list into an Oid list. Note that at this point we
+ * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
+ * there shouldn't be any additional work needed to support this case.
+ */
+ foreach(cell, stmt->grantees)
+ {
+ RoleSpec *grantee = (RoleSpec *) lfirst(cell);
+ Oid grantee_uid;
+
+ switch (grantee->roletype)
+ {
+ case ROLESPEC_PUBLIC:
+ grantee_uid = ACL_ID_PUBLIC;
+ break;
+ default:
+ grantee_uid = get_rolespec_oid(grantee, false);
+ break;
+ }
+ istmt.grantees = lappend_oid(istmt.grantees, grantee_uid);
+ }
+
+ /*
+ * Convert stmt->privileges, a list of AccessPriv nodes, into an AclMode
+ * bitmask. Note: objtype can't be OBJECT_COLUMN.
+ */
+ switch (stmt->objtype)
+ {
+ case OBJECT_TABLE:
+
+ /*
+ * Because this might be a sequence, we test both relation and
+ * sequence bits, and later do a more limited test when we know
+ * the object type.
+ */
+ all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE;
+ errormsg = gettext_noop("invalid privilege type %s for relation");
+ break;
+ case OBJECT_SEQUENCE:
+ all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ errormsg = gettext_noop("invalid privilege type %s for sequence");
+ break;
+ case OBJECT_DATABASE:
+ all_privileges = ACL_ALL_RIGHTS_DATABASE;
+ errormsg = gettext_noop("invalid privilege type %s for database");
+ break;
+ case OBJECT_DOMAIN:
+ all_privileges = ACL_ALL_RIGHTS_TYPE;
+ errormsg = gettext_noop("invalid privilege type %s for domain");
+ break;
+ case OBJECT_FUNCTION:
+ all_privileges = ACL_ALL_RIGHTS_FUNCTION;
+ errormsg = gettext_noop("invalid privilege type %s for function");
+ break;
+ case OBJECT_LANGUAGE:
+ all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
+ errormsg = gettext_noop("invalid privilege type %s for language");
+ break;
+ case OBJECT_LARGEOBJECT:
+ all_privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
+ errormsg = gettext_noop("invalid privilege type %s for large object");
+ break;
+ case OBJECT_SCHEMA:
+ all_privileges = ACL_ALL_RIGHTS_SCHEMA;
+ errormsg = gettext_noop("invalid privilege type %s for schema");
+ break;
+ case OBJECT_PROCEDURE:
+ all_privileges = ACL_ALL_RIGHTS_FUNCTION;
+ errormsg = gettext_noop("invalid privilege type %s for procedure");
+ break;
+ case OBJECT_ROUTINE:
+ all_privileges = ACL_ALL_RIGHTS_FUNCTION;
+ errormsg = gettext_noop("invalid privilege type %s for routine");
+ break;
+ case OBJECT_TABLESPACE:
+ all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
+ errormsg = gettext_noop("invalid privilege type %s for tablespace");
+ break;
+ case OBJECT_TYPE:
+ all_privileges = ACL_ALL_RIGHTS_TYPE;
+ errormsg = gettext_noop("invalid privilege type %s for type");
+ break;
+ case OBJECT_FDW:
+ all_privileges = ACL_ALL_RIGHTS_FDW;
+ errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
+ errormsg = gettext_noop("invalid privilege type %s for foreign server");
+ break;
+ default:
+ elog(ERROR, "unrecognized GrantStmt.objtype: %d",
+ (int) stmt->objtype);
+ /* keep compiler quiet */
+ all_privileges = ACL_NO_RIGHTS;
+ errormsg = NULL;
+ }
+
+ if (stmt->privileges == NIL)
+ {
+ istmt.all_privs = true;
+
+ /*
+ * will be turned into ACL_ALL_RIGHTS_* by the internal routines
+ * depending on the object type
+ */
+ istmt.privileges = ACL_NO_RIGHTS;
+ }
+ else
+ {
+ istmt.all_privs = false;
+ istmt.privileges = ACL_NO_RIGHTS;
+
+ foreach(cell, stmt->privileges)
+ {
+ AccessPriv *privnode = (AccessPriv *) lfirst(cell);
+ AclMode priv;
+
+ /*
+ * If it's a column-level specification, we just set it aside in
+ * col_privs for the moment; but insist it's for a relation.
+ */
+ if (privnode->cols)
+ {
+ if (stmt->objtype != OBJECT_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("column privileges are only valid for relations")));
+ istmt.col_privs = lappend(istmt.col_privs, privnode);
+ continue;
+ }
+
+ if (privnode->priv_name == NULL) /* parser mistake? */
+ elog(ERROR, "AccessPriv node must specify privilege or columns");
+ priv = string_to_privilege(privnode->priv_name);
+
+ if (priv & ~((AclMode) all_privileges))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg(errormsg, privilege_to_string(priv))));
+
+ istmt.privileges |= priv;
+ }
+ }
+
+ ExecGrantStmt_oids(&istmt);
+}
+
+/*
+ * ExecGrantStmt_oids
+ *
+ * Internal entry point for granting and revoking privileges.
+ */
+static void
+ExecGrantStmt_oids(InternalGrant *istmt)
+{
+ switch (istmt->objtype)
+ {
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ ExecGrant_Relation(istmt);
+ break;
+ case OBJECT_DATABASE:
+ ExecGrant_Database(istmt);
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ ExecGrant_Type(istmt);
+ break;
+ case OBJECT_FDW:
+ ExecGrant_Fdw(istmt);
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ ExecGrant_ForeignServer(istmt);
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ ExecGrant_Function(istmt);
+ break;
+ case OBJECT_LANGUAGE:
+ ExecGrant_Language(istmt);
+ break;
+ case OBJECT_LARGEOBJECT:
+ ExecGrant_Largeobject(istmt);
+ break;
+ case OBJECT_SCHEMA:
+ ExecGrant_Namespace(istmt);
+ break;
+ case OBJECT_TABLESPACE:
+ ExecGrant_Tablespace(istmt);
+ break;
+ default:
+ elog(ERROR, "unrecognized GrantStmt.objtype: %d",
+ (int) istmt->objtype);
+ }
+
+ /*
+ * Pass the info to event triggers about the just-executed GRANT. Note
+ * that we prefer to do it after actually executing it, because that gives
+ * the functions a chance to adjust the istmt with privileges actually
+ * granted.
+ */
+ if (EventTriggerSupportsObjectType(istmt->objtype))
+ EventTriggerCollectGrant(istmt);
+}
+
+/*
+ * objectNamesToOids
+ *
+ * Turn a list of object names of a given type into an Oid list.
+ *
+ * XXX: This function doesn't take any sort of locks on the objects whose
+ * names it looks up. In the face of concurrent DDL, we might easily latch
+ * onto an old version of an object, causing the GRANT or REVOKE statement
+ * to fail.
+ */
+static List *
+objectNamesToOids(ObjectType objtype, List *objnames)
+{
+ List *objects = NIL;
+ ListCell *cell;
+
+ Assert(objnames != NIL);
+
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ foreach(cell, objnames)
+ {
+ RangeVar *relvar = (RangeVar *) lfirst(cell);
+ Oid relOid;
+
+ relOid = RangeVarGetRelid(relvar, NoLock, false);
+ objects = lappend_oid(objects, relOid);
+ }
+ break;
+ case OBJECT_DATABASE:
+ foreach(cell, objnames)
+ {
+ char *dbname = strVal(lfirst(cell));
+ Oid dbid;
+
+ dbid = get_database_oid(dbname, false);
+ objects = lappend_oid(objects, dbid);
+ }
+ break;
+ case OBJECT_DOMAIN:
+ case OBJECT_TYPE:
+ foreach(cell, objnames)
+ {
+ List *typname = (List *) lfirst(cell);
+ Oid oid;
+
+ oid = typenameTypeId(NULL, makeTypeNameFromNameList(typname));
+ objects = lappend_oid(objects, oid);
+ }
+ break;
+ case OBJECT_FUNCTION:
+ foreach(cell, objnames)
+ {
+ ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
+ Oid funcid;
+
+ funcid = LookupFuncWithArgs(OBJECT_FUNCTION, func, false);
+ objects = lappend_oid(objects, funcid);
+ }
+ break;
+ case OBJECT_LANGUAGE:
+ foreach(cell, objnames)
+ {
+ char *langname = strVal(lfirst(cell));
+ Oid oid;
+
+ oid = get_language_oid(langname, false);
+ objects = lappend_oid(objects, oid);
+ }
+ break;
+ case OBJECT_LARGEOBJECT:
+ foreach(cell, objnames)
+ {
+ Oid lobjOid = oidparse(lfirst(cell));
+
+ if (!LargeObjectExists(lobjOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("large object %u does not exist",
+ lobjOid)));
+
+ objects = lappend_oid(objects, lobjOid);
+ }
+ break;
+ case OBJECT_SCHEMA:
+ foreach(cell, objnames)
+ {
+ char *nspname = strVal(lfirst(cell));
+ Oid oid;
+
+ oid = get_namespace_oid(nspname, false);
+ objects = lappend_oid(objects, oid);
+ }
+ break;
+ case OBJECT_PROCEDURE:
+ foreach(cell, objnames)
+ {
+ ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
+ Oid procid;
+
+ procid = LookupFuncWithArgs(OBJECT_PROCEDURE, func, false);
+ objects = lappend_oid(objects, procid);
+ }
+ break;
+ case OBJECT_ROUTINE:
+ foreach(cell, objnames)
+ {
+ ObjectWithArgs *func = (ObjectWithArgs *) lfirst(cell);
+ Oid routid;
+
+ routid = LookupFuncWithArgs(OBJECT_ROUTINE, func, false);
+ objects = lappend_oid(objects, routid);
+ }
+ break;
+ case OBJECT_TABLESPACE:
+ foreach(cell, objnames)
+ {
+ char *spcname = strVal(lfirst(cell));
+ Oid spcoid;
+
+ spcoid = get_tablespace_oid(spcname, false);
+ objects = lappend_oid(objects, spcoid);
+ }
+ break;
+ case OBJECT_FDW:
+ foreach(cell, objnames)
+ {
+ char *fdwname = strVal(lfirst(cell));
+ Oid fdwid = get_foreign_data_wrapper_oid(fdwname, false);
+
+ objects = lappend_oid(objects, fdwid);
+ }
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ foreach(cell, objnames)
+ {
+ char *srvname = strVal(lfirst(cell));
+ Oid srvid = get_foreign_server_oid(srvname, false);
+
+ objects = lappend_oid(objects, srvid);
+ }
+ break;
+ default:
+ elog(ERROR, "unrecognized GrantStmt.objtype: %d",
+ (int) objtype);
+ }
+
+ return objects;
+}
+
+/*
+ * objectsInSchemaToOids
+ *
+ * Find all objects of a given type in specified schemas, and make a list
+ * of their Oids. We check USAGE privilege on the schemas, but there is
+ * no privilege checking on the individual objects here.
+ */
+static List *
+objectsInSchemaToOids(ObjectType objtype, List *nspnames)
+{
+ List *objects = NIL;
+ ListCell *cell;
+
+ foreach(cell, nspnames)
+ {
+ char *nspname = strVal(lfirst(cell));
+ Oid namespaceId;
+ List *objs;
+
+ namespaceId = LookupExplicitNamespace(nspname, false);
+
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
+ objects = list_concat(objects, objs);
+ objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
+ objects = list_concat(objects, objs);
+ objs = getRelationsInNamespace(namespaceId, RELKIND_MATVIEW);
+ objects = list_concat(objects, objs);
+ objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
+ objects = list_concat(objects, objs);
+ objs = getRelationsInNamespace(namespaceId, RELKIND_PARTITIONED_TABLE);
+ objects = list_concat(objects, objs);
+ break;
+ case OBJECT_SEQUENCE:
+ objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
+ objects = list_concat(objects, objs);
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ {
+ ScanKeyData key[2];
+ int keycount;
+ Relation rel;
+ TableScanDesc scan;
+ HeapTuple tuple;
+
+ keycount = 0;
+ ScanKeyInit(&key[keycount++],
+ Anum_pg_proc_pronamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(namespaceId));
+
+ if (objtype == OBJECT_FUNCTION)
+ /* includes aggregates and window functions */
+ ScanKeyInit(&key[keycount++],
+ Anum_pg_proc_prokind,
+ BTEqualStrategyNumber, F_CHARNE,
+ CharGetDatum(PROKIND_PROCEDURE));
+ else if (objtype == OBJECT_PROCEDURE)
+ ScanKeyInit(&key[keycount++],
+ Anum_pg_proc_prokind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ CharGetDatum(PROKIND_PROCEDURE));
+
+ rel = table_open(ProcedureRelationId, AccessShareLock);
+ scan = table_beginscan_catalog(rel, keycount, key);
+
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ Oid oid = ((Form_pg_proc) GETSTRUCT(tuple))->oid;
+
+ objects = lappend_oid(objects, oid);
+ }
+
+ table_endscan(scan);
+ table_close(rel, AccessShareLock);
+ }
+ break;
+ default:
+ /* should not happen */
+ elog(ERROR, "unrecognized GrantStmt.objtype: %d",
+ (int) objtype);
+ }
+ }
+
+ return objects;
+}
+
+/*
+ * getRelationsInNamespace
+ *
+ * Return Oid list of relations in given namespace filtered by relation kind
+ */
+static List *
+getRelationsInNamespace(Oid namespaceId, char relkind)
+{
+ List *relations = NIL;
+ ScanKeyData key[2];
+ Relation rel;
+ TableScanDesc scan;
+ HeapTuple tuple;
+
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(namespaceId));
+ ScanKeyInit(&key[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ CharGetDatum(relkind));
+
+ rel = table_open(RelationRelationId, AccessShareLock);
+ scan = table_beginscan_catalog(rel, 2, key);
+
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ Oid oid = ((Form_pg_class) GETSTRUCT(tuple))->oid;
+
+ relations = lappend_oid(relations, oid);
+ }
+
+ table_endscan(scan);
+ table_close(rel, AccessShareLock);
+
+ return relations;
+}
+
+
+/*
+ * ALTER DEFAULT PRIVILEGES statement
+ */
+void
+ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *stmt)
+{
+ GrantStmt *action = stmt->action;
+ InternalDefaultACL iacls;
+ ListCell *cell;
+ List *rolespecs = NIL;
+ List *nspnames = NIL;
+ DefElem *drolespecs = NULL;
+ DefElem *dnspnames = NULL;
+ AclMode all_privileges;
+ const char *errormsg;
+
+ /* Deconstruct the "options" part of the statement */
+ foreach(cell, stmt->options)
+ {
+ DefElem *defel = (DefElem *) lfirst(cell);
+
+ if (strcmp(defel->defname, "schemas") == 0)
+ {
+ if (dnspnames)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
+ dnspnames = defel;
+ }
+ else if (strcmp(defel->defname, "roles") == 0)
+ {
+ if (drolespecs)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options"),
+ parser_errposition(pstate, defel->location)));
+ drolespecs = defel;
+ }
+ else
+ elog(ERROR, "option \"%s\" not recognized", defel->defname);
+ }
+
+ if (dnspnames)
+ nspnames = (List *) dnspnames->arg;
+ if (drolespecs)
+ rolespecs = (List *) drolespecs->arg;
+
+ /* Prepare the InternalDefaultACL representation of the statement */
+ /* roleid to be filled below */
+ /* nspid to be filled in SetDefaultACLsInSchemas */
+ iacls.is_grant = action->is_grant;
+ iacls.objtype = action->objtype;
+ /* all_privs to be filled below */
+ /* privileges to be filled below */
+ iacls.grantees = NIL; /* filled below */
+ iacls.grant_option = action->grant_option;
+ iacls.behavior = action->behavior;
+
+ /*
+ * Convert the RoleSpec list into an Oid list. Note that at this point we
+ * insert an ACL_ID_PUBLIC into the list if appropriate, so downstream
+ * there shouldn't be any additional work needed to support this case.
+ */
+ foreach(cell, action->grantees)
+ {
+ RoleSpec *grantee = (RoleSpec *) lfirst(cell);
+ Oid grantee_uid;
+
+ switch (grantee->roletype)
+ {
+ case ROLESPEC_PUBLIC:
+ grantee_uid = ACL_ID_PUBLIC;
+ break;
+ default:
+ grantee_uid = get_rolespec_oid(grantee, false);
+ break;
+ }
+ iacls.grantees = lappend_oid(iacls.grantees, grantee_uid);
+ }
+
+ /*
+ * Convert action->privileges, a list of privilege strings, into an
+ * AclMode bitmask.
+ */
+ switch (action->objtype)
+ {
+ case OBJECT_TABLE:
+ all_privileges = ACL_ALL_RIGHTS_RELATION;
+ errormsg = gettext_noop("invalid privilege type %s for relation");
+ break;
+ case OBJECT_SEQUENCE:
+ all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ errormsg = gettext_noop("invalid privilege type %s for sequence");
+ break;
+ case OBJECT_FUNCTION:
+ all_privileges = ACL_ALL_RIGHTS_FUNCTION;
+ errormsg = gettext_noop("invalid privilege type %s for function");
+ break;
+ case OBJECT_PROCEDURE:
+ all_privileges = ACL_ALL_RIGHTS_FUNCTION;
+ errormsg = gettext_noop("invalid privilege type %s for procedure");
+ break;
+ case OBJECT_ROUTINE:
+ all_privileges = ACL_ALL_RIGHTS_FUNCTION;
+ errormsg = gettext_noop("invalid privilege type %s for routine");
+ break;
+ case OBJECT_TYPE:
+ all_privileges = ACL_ALL_RIGHTS_TYPE;
+ errormsg = gettext_noop("invalid privilege type %s for type");
+ break;
+ case OBJECT_SCHEMA:
+ all_privileges = ACL_ALL_RIGHTS_SCHEMA;
+ errormsg = gettext_noop("invalid privilege type %s for schema");
+ break;
+ default:
+ elog(ERROR, "unrecognized GrantStmt.objtype: %d",
+ (int) action->objtype);
+ /* keep compiler quiet */
+ all_privileges = ACL_NO_RIGHTS;
+ errormsg = NULL;
+ }
+
+ if (action->privileges == NIL)
+ {
+ iacls.all_privs = true;
+
+ /*
+ * will be turned into ACL_ALL_RIGHTS_* by the internal routines
+ * depending on the object type
+ */
+ iacls.privileges = ACL_NO_RIGHTS;
+ }
+ else
+ {
+ iacls.all_privs = false;
+ iacls.privileges = ACL_NO_RIGHTS;
+
+ foreach(cell, action->privileges)
+ {
+ AccessPriv *privnode = (AccessPriv *) lfirst(cell);
+ AclMode priv;
+
+ if (privnode->cols)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("default privileges cannot be set for columns")));
+
+ if (privnode->priv_name == NULL) /* parser mistake? */
+ elog(ERROR, "AccessPriv node must specify privilege");
+ priv = string_to_privilege(privnode->priv_name);
+
+ if (priv & ~((AclMode) all_privileges))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg(errormsg, privilege_to_string(priv))));
+
+ iacls.privileges |= priv;
+ }
+ }
+
+ if (rolespecs == NIL)
+ {
+ /* Set permissions for myself */
+ iacls.roleid = GetUserId();
+
+ SetDefaultACLsInSchemas(&iacls, nspnames);
+ }
+ else
+ {
+ /* Look up the role OIDs and do permissions checks */
+ ListCell *rolecell;
+
+ foreach(rolecell, rolespecs)
+ {
+ RoleSpec *rolespec = lfirst(rolecell);
+
+ iacls.roleid = get_rolespec_oid(rolespec, false);
+
+ /*
+ * We insist that calling user be a member of each target role. If
+ * he has that, he could become that role anyway via SET ROLE, so
+ * FOR ROLE is just a syntactic convenience and doesn't give any
+ * special privileges.
+ */
+ check_is_member_of_role(GetUserId(), iacls.roleid);
+
+ SetDefaultACLsInSchemas(&iacls, nspnames);
+ }
+ }
+}
+
+/*
+ * Process ALTER DEFAULT PRIVILEGES for a list of target schemas
+ *
+ * All fields of *iacls except nspid were filled already
+ */
+static void
+SetDefaultACLsInSchemas(InternalDefaultACL *iacls, List *nspnames)
+{
+ if (nspnames == NIL)
+ {
+ /* Set database-wide permissions if no schema was specified */
+ iacls->nspid = InvalidOid;
+
+ SetDefaultACL(iacls);
+ }
+ else
+ {
+ /* Look up the schema OIDs and set permissions for each one */
+ ListCell *nspcell;
+
+ foreach(nspcell, nspnames)
+ {
+ char *nspname = strVal(lfirst(nspcell));
+
+ iacls->nspid = get_namespace_oid(nspname, false);
+
+ /*
+ * We used to insist that the target role have CREATE privileges
+ * on the schema, since without that it wouldn't be able to create
+ * an object for which these default privileges would apply.
+ * However, this check proved to be more confusing than helpful,
+ * and it also caused certain database states to not be
+ * dumpable/restorable, since revoking CREATE doesn't cause
+ * default privileges for the schema to go away. So now, we just
+ * allow the ALTER; if the user lacks CREATE he'll find out when
+ * he tries to create an object.
+ */
+
+ SetDefaultACL(iacls);
+ }
+ }
+}
+
+
+/*
+ * Create or update a pg_default_acl entry
+ */
+static void
+SetDefaultACL(InternalDefaultACL *iacls)
+{
+ AclMode this_privileges = iacls->privileges;
+ char objtype;
+ Relation rel;
+ HeapTuple tuple;
+ bool isNew;
+ Acl *def_acl;
+ Acl *old_acl;
+ Acl *new_acl;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_default_acl];
+ bool nulls[Natts_pg_default_acl];
+ bool replaces[Natts_pg_default_acl];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+
+ rel = table_open(DefaultAclRelationId, RowExclusiveLock);
+
+ /*
+ * The default for a global entry is the hard-wired default ACL for the
+ * particular object type. The default for non-global entries is an empty
+ * ACL. This must be so because global entries replace the hard-wired
+ * defaults, while others are added on.
+ */
+ if (!OidIsValid(iacls->nspid))
+ def_acl = acldefault(iacls->objtype, iacls->roleid);
+ else
+ def_acl = make_empty_acl();
+
+ /*
+ * Convert ACL object type to pg_default_acl object type and handle
+ * all_privs option
+ */
+ switch (iacls->objtype)
+ {
+ case OBJECT_TABLE:
+ objtype = DEFACLOBJ_RELATION;
+ if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
+ this_privileges = ACL_ALL_RIGHTS_RELATION;
+ break;
+
+ case OBJECT_SEQUENCE:
+ objtype = DEFACLOBJ_SEQUENCE;
+ if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
+ this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ break;
+
+ case OBJECT_FUNCTION:
+ objtype = DEFACLOBJ_FUNCTION;
+ if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
+ this_privileges = ACL_ALL_RIGHTS_FUNCTION;
+ break;
+
+ case OBJECT_TYPE:
+ objtype = DEFACLOBJ_TYPE;
+ if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
+ this_privileges = ACL_ALL_RIGHTS_TYPE;
+ break;
+
+ case OBJECT_SCHEMA:
+ if (OidIsValid(iacls->nspid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS")));
+ objtype = DEFACLOBJ_NAMESPACE;
+ if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
+ this_privileges = ACL_ALL_RIGHTS_SCHEMA;
+ break;
+
+ default:
+ elog(ERROR, "unrecognized objtype: %d",
+ (int) iacls->objtype);
+ objtype = 0; /* keep compiler quiet */
+ break;
+ }
+
+ /* Search for existing row for this object type in catalog */
+ tuple = SearchSysCache3(DEFACLROLENSPOBJ,
+ ObjectIdGetDatum(iacls->roleid),
+ ObjectIdGetDatum(iacls->nspid),
+ CharGetDatum(objtype));
+
+ if (HeapTupleIsValid(tuple))
+ {
+ Datum aclDatum;
+ bool isNull;
+
+ aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
+ Anum_pg_default_acl_defaclacl,
+ &isNull);
+ if (!isNull)
+ old_acl = DatumGetAclPCopy(aclDatum);
+ else
+ old_acl = NULL; /* this case shouldn't happen, probably */
+ isNew = false;
+ }
+ else
+ {
+ old_acl = NULL;
+ isNew = true;
+ }
+
+ if (old_acl != NULL)
+ {
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information. Collect data before
+ * merge_acl_with_grant throws away old_acl.
+ */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+ else
+ {
+ /* If no or null entry, start with the default ACL value */
+ old_acl = aclcopy(def_acl);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+
+ /*
+ * Generate new ACL. Grantor of rights is always the same as the target
+ * role.
+ */
+ new_acl = merge_acl_with_grant(old_acl,
+ iacls->is_grant,
+ iacls->grant_option,
+ iacls->behavior,
+ iacls->grantees,
+ this_privileges,
+ iacls->roleid,
+ iacls->roleid);
+
+ /*
+ * If the result is the same as the default value, we do not need an
+ * explicit pg_default_acl entry, and should in fact remove the entry if
+ * it exists. Must sort both arrays to compare properly.
+ */
+ aclitemsort(new_acl);
+ aclitemsort(def_acl);
+ if (aclequal(new_acl, def_acl))
+ {
+ /* delete old entry, if indeed there is one */
+ if (!isNew)
+ {
+ ObjectAddress myself;
+
+ /*
+ * The dependency machinery will take care of removing all
+ * associated dependency entries. We use DROP_RESTRICT since
+ * there shouldn't be anything depending on this entry.
+ */
+ myself.classId = DefaultAclRelationId;
+ myself.objectId = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
+ myself.objectSubId = 0;
+
+ performDeletion(&myself, DROP_RESTRICT, 0);
+ }
+ }
+ else
+ {
+ Oid defAclOid;
+
+ /* Prepare to insert or update pg_default_acl entry */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ if (isNew)
+ {
+ /* insert new entry */
+ defAclOid = GetNewOidWithIndex(rel, DefaultAclOidIndexId,
+ Anum_pg_default_acl_oid);
+ values[Anum_pg_default_acl_oid - 1] = ObjectIdGetDatum(defAclOid);
+ values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid);
+ values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid);
+ values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
+ values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+ CatalogTupleInsert(rel, newtuple);
+ }
+ else
+ {
+ defAclOid = ((Form_pg_default_acl) GETSTRUCT(tuple))->oid;
+
+ /* update existing entry */
+ values[Anum_pg_default_acl_defaclacl - 1] = PointerGetDatum(new_acl);
+ replaces[Anum_pg_default_acl_defaclacl - 1] = true;
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
+ values, nulls, replaces);
+ CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
+ }
+
+ /* these dependencies don't change in an update */
+ if (isNew)
+ {
+ /* dependency on role */
+ recordDependencyOnOwner(DefaultAclRelationId, defAclOid,
+ iacls->roleid);
+
+ /* dependency on namespace */
+ if (OidIsValid(iacls->nspid))
+ {
+ ObjectAddress myself,
+ referenced;
+
+ myself.classId = DefaultAclRelationId;
+ myself.objectId = defAclOid;
+ myself.objectSubId = 0;
+
+ referenced.classId = NamespaceRelationId;
+ referenced.objectId = iacls->nspid;
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+ }
+ }
+
+ /*
+ * Update the shared dependency ACL info
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ updateAclDependencies(DefaultAclRelationId,
+ defAclOid, 0,
+ iacls->roleid,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ if (isNew)
+ InvokeObjectPostCreateHook(DefaultAclRelationId, defAclOid, 0);
+ else
+ InvokeObjectPostAlterHook(DefaultAclRelationId, defAclOid, 0);
+ }
+
+ if (HeapTupleIsValid(tuple))
+ ReleaseSysCache(tuple);
+
+ table_close(rel, RowExclusiveLock);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+}
+
+
+/*
+ * RemoveRoleFromObjectACL
+ *
+ * Used by shdepDropOwned to remove mentions of a role in ACLs
+ */
+void
+RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
+{
+ if (classid == DefaultAclRelationId)
+ {
+ InternalDefaultACL iacls;
+ Form_pg_default_acl pg_default_acl_tuple;
+ Relation rel;
+ ScanKeyData skey[1];
+ SysScanDesc scan;
+ HeapTuple tuple;
+
+ /* first fetch info needed by SetDefaultACL */
+ rel = table_open(DefaultAclRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_default_acl_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objid));
+
+ scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
+ NULL, 1, skey);
+
+ tuple = systable_getnext(scan);
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "could not find tuple for default ACL %u", objid);
+
+ pg_default_acl_tuple = (Form_pg_default_acl) GETSTRUCT(tuple);
+
+ iacls.roleid = pg_default_acl_tuple->defaclrole;
+ iacls.nspid = pg_default_acl_tuple->defaclnamespace;
+
+ switch (pg_default_acl_tuple->defaclobjtype)
+ {
+ case DEFACLOBJ_RELATION:
+ iacls.objtype = OBJECT_TABLE;
+ break;
+ case DEFACLOBJ_SEQUENCE:
+ iacls.objtype = OBJECT_SEQUENCE;
+ break;
+ case DEFACLOBJ_FUNCTION:
+ iacls.objtype = OBJECT_FUNCTION;
+ break;
+ case DEFACLOBJ_TYPE:
+ iacls.objtype = OBJECT_TYPE;
+ break;
+ case DEFACLOBJ_NAMESPACE:
+ iacls.objtype = OBJECT_SCHEMA;
+ break;
+ default:
+ /* Shouldn't get here */
+ elog(ERROR, "unexpected default ACL type: %d",
+ (int) pg_default_acl_tuple->defaclobjtype);
+ break;
+ }
+
+ systable_endscan(scan);
+ table_close(rel, AccessShareLock);
+
+ iacls.is_grant = false;
+ iacls.all_privs = true;
+ iacls.privileges = ACL_NO_RIGHTS;
+ iacls.grantees = list_make1_oid(roleid);
+ iacls.grant_option = false;
+ iacls.behavior = DROP_CASCADE;
+
+ /* Do it */
+ SetDefaultACL(&iacls);
+ }
+ else
+ {
+ InternalGrant istmt;
+
+ switch (classid)
+ {
+ case RelationRelationId:
+ /* it's OK to use TABLE for a sequence */
+ istmt.objtype = OBJECT_TABLE;
+ break;
+ case DatabaseRelationId:
+ istmt.objtype = OBJECT_DATABASE;
+ break;
+ case TypeRelationId:
+ istmt.objtype = OBJECT_TYPE;
+ break;
+ case ProcedureRelationId:
+ istmt.objtype = OBJECT_ROUTINE;
+ break;
+ case LanguageRelationId:
+ istmt.objtype = OBJECT_LANGUAGE;
+ break;
+ case LargeObjectRelationId:
+ istmt.objtype = OBJECT_LARGEOBJECT;
+ break;
+ case NamespaceRelationId:
+ istmt.objtype = OBJECT_SCHEMA;
+ break;
+ case TableSpaceRelationId:
+ istmt.objtype = OBJECT_TABLESPACE;
+ break;
+ case ForeignServerRelationId:
+ istmt.objtype = OBJECT_FOREIGN_SERVER;
+ break;
+ case ForeignDataWrapperRelationId:
+ istmt.objtype = OBJECT_FDW;
+ break;
+ default:
+ elog(ERROR, "unexpected object class %u", classid);
+ break;
+ }
+ istmt.is_grant = false;
+ istmt.objects = list_make1_oid(objid);
+ istmt.all_privs = true;
+ istmt.privileges = ACL_NO_RIGHTS;
+ istmt.col_privs = NIL;
+ istmt.grantees = list_make1_oid(roleid);
+ istmt.grant_option = false;
+ istmt.behavior = DROP_CASCADE;
+
+ ExecGrantStmt_oids(&istmt);
+ }
+}
+
+
+/*
+ * Remove a pg_default_acl entry
+ */
+void
+RemoveDefaultACLById(Oid defaclOid)
+{
+ Relation rel;
+ ScanKeyData skey[1];
+ SysScanDesc scan;
+ HeapTuple tuple;
+
+ rel = table_open(DefaultAclRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_default_acl_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(defaclOid));
+
+ scan = systable_beginscan(rel, DefaultAclOidIndexId, true,
+ NULL, 1, skey);
+
+ tuple = systable_getnext(scan);
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "could not find tuple for default ACL %u", defaclOid);
+
+ CatalogTupleDelete(rel, &tuple->t_self);
+
+ systable_endscan(scan);
+ table_close(rel, RowExclusiveLock);
+}
+
+
+/*
+ * expand_col_privileges
+ *
+ * OR the specified privilege(s) into per-column array entries for each
+ * specified attribute. The per-column array is indexed starting at
+ * FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
+ */
+static void
+expand_col_privileges(List *colnames, Oid table_oid,
+ AclMode this_privileges,
+ AclMode *col_privileges,
+ int num_col_privileges)
+{
+ ListCell *cell;
+
+ foreach(cell, colnames)
+ {
+ char *colname = strVal(lfirst(cell));
+ AttrNumber attnum;
+
+ attnum = get_attnum(table_oid, colname);
+ if (attnum == InvalidAttrNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ colname, get_rel_name(table_oid))));
+ attnum -= FirstLowInvalidHeapAttributeNumber;
+ if (attnum <= 0 || attnum >= num_col_privileges)
+ elog(ERROR, "column number out of range"); /* safety check */
+ col_privileges[attnum] |= this_privileges;
+ }
+}
+
+/*
+ * expand_all_col_privileges
+ *
+ * OR the specified privilege(s) into per-column array entries for each valid
+ * attribute of a relation. The per-column array is indexed starting at
+ * FirstLowInvalidHeapAttributeNumber, up to relation's last attribute.
+ */
+static void
+expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
+ AclMode this_privileges,
+ AclMode *col_privileges,
+ int num_col_privileges)
+{
+ AttrNumber curr_att;
+
+ Assert(classForm->relnatts - FirstLowInvalidHeapAttributeNumber < num_col_privileges);
+ for (curr_att = FirstLowInvalidHeapAttributeNumber + 1;
+ curr_att <= classForm->relnatts;
+ curr_att++)
+ {
+ HeapTuple attTuple;
+ bool isdropped;
+
+ if (curr_att == InvalidAttrNumber)
+ continue;
+
+ /* Views don't have any system columns at all */
+ if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
+ continue;
+
+ attTuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(table_oid),
+ Int16GetDatum(curr_att));
+ if (!HeapTupleIsValid(attTuple))
+ elog(ERROR, "cache lookup failed for attribute %d of relation %u",
+ curr_att, table_oid);
+
+ isdropped = ((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped;
+
+ ReleaseSysCache(attTuple);
+
+ /* ignore dropped columns */
+ if (isdropped)
+ continue;
+
+ col_privileges[curr_att - FirstLowInvalidHeapAttributeNumber] |= this_privileges;
+ }
+}
+
+/*
+ * This processes attributes, but expects to be called from
+ * ExecGrant_Relation, not directly from ExecuteGrantStmt.
+ */
+static void
+ExecGrant_Attribute(InternalGrant *istmt, Oid relOid, const char *relname,
+ AttrNumber attnum, Oid ownerId, AclMode col_privileges,
+ Relation attRelation, const Acl *old_rel_acl)
+{
+ HeapTuple attr_tuple;
+ Form_pg_attribute pg_attribute_tuple;
+ Acl *old_acl;
+ Acl *new_acl;
+ Acl *merged_acl;
+ Datum aclDatum;
+ bool isNull;
+ Oid grantorId;
+ AclMode avail_goptions;
+ bool need_update;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_attribute];
+ bool nulls[Natts_pg_attribute];
+ bool replaces[Natts_pg_attribute];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+
+ attr_tuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(relOid),
+ Int16GetDatum(attnum));
+ if (!HeapTupleIsValid(attr_tuple))
+ elog(ERROR, "cache lookup failed for attribute %d of relation %u",
+ attnum, relOid);
+ pg_attribute_tuple = (Form_pg_attribute) GETSTRUCT(attr_tuple);
+
+ /*
+ * Get working copy of existing ACL. If there's no ACL, substitute the
+ * proper default.
+ */
+ aclDatum = SysCacheGetAttr(ATTNUM, attr_tuple, Anum_pg_attribute_attacl,
+ &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(OBJECT_COLUMN, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /*
+ * In select_best_grantor we should consider existing table-level ACL bits
+ * as well as the per-column ACL. Build a new ACL that is their
+ * concatenation. (This is a bit cheap and dirty compared to merging them
+ * properly with no duplications, but it's all we need here.)
+ */
+ merged_acl = aclconcat(old_rel_acl, old_acl);
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), col_privileges,
+ merged_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ pfree(merged_acl);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages. Note: we don't track
+ * whether the user actually used the ALL PRIVILEGES(columns) syntax for
+ * each column; we just approximate it by whether all the possible
+ * privileges are specified now. Since the all_privs flag only determines
+ * whether a warning is issued, this seems close enough.
+ */
+ col_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ (col_privileges == ACL_ALL_RIGHTS_COLUMN),
+ col_privileges,
+ relOid, grantorId, OBJECT_COLUMN,
+ relname, attnum,
+ NameStr(pg_attribute_tuple->attname));
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option,
+ istmt->behavior, istmt->grantees,
+ col_privileges, grantorId,
+ ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ /*
+ * If the updated ACL is empty, we can set attacl to null, and maybe even
+ * avoid an update of the pg_attribute row. This is worth testing because
+ * we'll come through here multiple times for any relation-level REVOKE,
+ * even if there were never any column GRANTs. Note we are assuming that
+ * the "default" ACL state for columns is empty.
+ */
+ if (ACL_NUM(new_acl) > 0)
+ {
+ values[Anum_pg_attribute_attacl - 1] = PointerGetDatum(new_acl);
+ need_update = true;
+ }
+ else
+ {
+ nulls[Anum_pg_attribute_attacl - 1] = true;
+ need_update = !isNull;
+ }
+ replaces[Anum_pg_attribute_attacl - 1] = true;
+
+ if (need_update)
+ {
+ newtuple = heap_modify_tuple(attr_tuple, RelationGetDescr(attRelation),
+ values, nulls, replaces);
+
+ CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
+
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(relOid, RelationRelationId, attnum,
+ ACL_NUM(new_acl) > 0 ? new_acl : NULL);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(RelationRelationId, relOid, attnum,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+ }
+
+ pfree(new_acl);
+
+ ReleaseSysCache(attr_tuple);
+}
+
+/*
+ * This processes both sequences and non-sequences.
+ */
+static void
+ExecGrant_Relation(InternalGrant *istmt)
+{
+ Relation relation;
+ Relation attRelation;
+ ListCell *cell;
+
+ relation = table_open(RelationRelationId, RowExclusiveLock);
+ attRelation = table_open(AttributeRelationId, RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid relOid = lfirst_oid(cell);
+ Datum aclDatum;
+ Form_pg_class pg_class_tuple;
+ bool isNull;
+ AclMode this_privileges;
+ AclMode *col_privileges;
+ int num_col_privileges;
+ bool have_col_privileges;
+ Acl *old_acl;
+ Acl *old_rel_acl;
+ int noldmembers;
+ Oid *oldmembers;
+ Oid ownerId;
+ HeapTuple tuple;
+ ListCell *cell_colprivs;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", relOid);
+ pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
+
+ /* Not sensible to grant on an index */
+ if (pg_class_tuple->relkind == RELKIND_INDEX ||
+ pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is an index",
+ NameStr(pg_class_tuple->relname))));
+
+ /* Composite types aren't tables either */
+ if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is a composite type",
+ NameStr(pg_class_tuple->relname))));
+
+ /* Used GRANT SEQUENCE on a non-sequence? */
+ if (istmt->objtype == OBJECT_SEQUENCE &&
+ pg_class_tuple->relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ NameStr(pg_class_tuple->relname))));
+
+ /* Adjust the default permissions based on object type */
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ {
+ if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
+ this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ else
+ this_privileges = ACL_ALL_RIGHTS_RELATION;
+ }
+ else
+ this_privileges = istmt->privileges;
+
+ /*
+ * The GRANT TABLE syntax can be used for sequences and non-sequences,
+ * so we have to look at the relkind to determine the supported
+ * permissions. The OR of table and sequence permissions were already
+ * checked.
+ */
+ if (istmt->objtype == OBJECT_TABLE)
+ {
+ if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
+ {
+ /*
+ * For backward compatibility, just throw a warning for
+ * invalid sequence permissions when using the non-sequence
+ * GRANT syntax.
+ */
+ if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
+ {
+ /*
+ * Mention the object name because the user needs to know
+ * which operations succeeded. This is required because
+ * WARNING allows the command to continue.
+ */
+ ereport(WARNING,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE privileges",
+ NameStr(pg_class_tuple->relname))));
+ this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
+ }
+ }
+ else
+ {
+ if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
+ {
+ /*
+ * USAGE is the only permission supported by sequences but
+ * not by non-sequences. Don't mention the object name
+ * because we didn't in the combined TABLE | SEQUENCE
+ * check.
+ */
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("invalid privilege type %s for table",
+ "USAGE")));
+ }
+ }
+ }
+
+ /*
+ * Set up array in which we'll accumulate any column privilege bits
+ * that need modification. The array is indexed such that entry [0]
+ * corresponds to FirstLowInvalidHeapAttributeNumber.
+ */
+ num_col_privileges = pg_class_tuple->relnatts - FirstLowInvalidHeapAttributeNumber + 1;
+ col_privileges = (AclMode *) palloc0(num_col_privileges * sizeof(AclMode));
+ have_col_privileges = false;
+
+ /*
+ * If we are revoking relation privileges that are also column
+ * privileges, we must implicitly revoke them from each column too,
+ * per SQL spec. (We don't need to implicitly add column privileges
+ * during GRANT because the permissions-checking code always checks
+ * both relation and per-column privileges.)
+ */
+ if (!istmt->is_grant &&
+ (this_privileges & ACL_ALL_RIGHTS_COLUMN) != 0)
+ {
+ expand_all_col_privileges(relOid, pg_class_tuple,
+ this_privileges & ACL_ALL_RIGHTS_COLUMN,
+ col_privileges,
+ num_col_privileges);
+ have_col_privileges = true;
+ }
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_class_tuple->relowner;
+ aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
+ &isNull);
+ if (isNull)
+ {
+ switch (pg_class_tuple->relkind)
+ {
+ case RELKIND_SEQUENCE:
+ old_acl = acldefault(OBJECT_SEQUENCE, ownerId);
+ break;
+ default:
+ old_acl = acldefault(OBJECT_TABLE, ownerId);
+ break;
+ }
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Need an extra copy of original rel ACL for column handling */
+ old_rel_acl = aclcopy(old_acl);
+
+ /*
+ * Handle relation-level privileges, if any were specified
+ */
+ if (this_privileges != ACL_NO_RIGHTS)
+ {
+ AclMode avail_goptions;
+ Acl *new_acl;
+ Oid grantorId;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_class];
+ bool nulls[Natts_pg_class];
+ bool replaces[Natts_pg_class];
+ int nnewmembers;
+ Oid *newmembers;
+ ObjectType objtype;
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), this_privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ switch (pg_class_tuple->relkind)
+ {
+ case RELKIND_SEQUENCE:
+ objtype = OBJECT_SEQUENCE;
+ break;
+ default:
+ objtype = OBJECT_TABLE;
+ break;
+ }
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit
+ * the standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, this_privileges,
+ relOid, grantorId, objtype,
+ NameStr(pg_class_tuple->relname),
+ 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl,
+ istmt->is_grant,
+ istmt->grant_option,
+ istmt->behavior,
+ istmt->grantees,
+ this_privileges,
+ grantorId,
+ ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct
+ * the shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_class_relacl - 1] = true;
+ values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
+ values, nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(relOid, RelationRelationId, 0, new_acl);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(RelationRelationId, relOid, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ pfree(new_acl);
+ }
+
+ /*
+ * Handle column-level privileges, if any were specified or implied.
+ * We first expand the user-specified column privileges into the
+ * array, and then iterate over all nonempty array entries.
+ */
+ foreach(cell_colprivs, istmt->col_privs)
+ {
+ AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
+
+ if (col_privs->priv_name == NULL)
+ this_privileges = ACL_ALL_RIGHTS_COLUMN;
+ else
+ this_privileges = string_to_privilege(col_privs->priv_name);
+
+ if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_COLUMN))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("invalid privilege type %s for column",
+ privilege_to_string(this_privileges))));
+
+ if (pg_class_tuple->relkind == RELKIND_SEQUENCE &&
+ this_privileges & ~((AclMode) ACL_SELECT))
+ {
+ /*
+ * The only column privilege allowed on sequences is SELECT.
+ * This is a warning not error because we do it that way for
+ * relation-level privileges.
+ */
+ ereport(WARNING,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("sequence \"%s\" only supports SELECT column privileges",
+ NameStr(pg_class_tuple->relname))));
+
+ this_privileges &= (AclMode) ACL_SELECT;
+ }
+
+ expand_col_privileges(col_privs->cols, relOid,
+ this_privileges,
+ col_privileges,
+ num_col_privileges);
+ have_col_privileges = true;
+ }
+
+ if (have_col_privileges)
+ {
+ AttrNumber i;
+
+ for (i = 0; i < num_col_privileges; i++)
+ {
+ if (col_privileges[i] == ACL_NO_RIGHTS)
+ continue;
+ ExecGrant_Attribute(istmt,
+ relOid,
+ NameStr(pg_class_tuple->relname),
+ i + FirstLowInvalidHeapAttributeNumber,
+ ownerId,
+ col_privileges[i],
+ attRelation,
+ old_rel_acl);
+ }
+ }
+
+ pfree(old_rel_acl);
+ pfree(col_privileges);
+
+ ReleaseSysCache(tuple);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(attRelation, RowExclusiveLock);
+ table_close(relation, RowExclusiveLock);
+}
+
+static void
+ExecGrant_Database(InternalGrant *istmt)
+{
+ Relation relation;
+ ListCell *cell;
+
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ istmt->privileges = ACL_ALL_RIGHTS_DATABASE;
+
+ relation = table_open(DatabaseRelationId, RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid datId = lfirst_oid(cell);
+ Form_pg_database pg_database_tuple;
+ Datum aclDatum;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *old_acl;
+ Acl *new_acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_database];
+ bool nulls[Natts_pg_database];
+ bool replaces[Natts_pg_database];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(datId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for database %u", datId);
+
+ pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_database_tuple->datdba;
+ aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
+ RelationGetDescr(relation), &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(OBJECT_DATABASE, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), istmt->privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, istmt->privileges,
+ datId, grantorId, OBJECT_DATABASE,
+ NameStr(pg_database_tuple->datname),
+ 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option, istmt->behavior,
+ istmt->grantees, this_privileges,
+ grantorId, ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_database_datacl - 1] = true;
+ values[Anum_pg_database_datacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
+ nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(DatabaseRelationId, pg_database_tuple->oid, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ ReleaseSysCache(tuple);
+
+ pfree(new_acl);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(relation, RowExclusiveLock);
+}
+
+static void
+ExecGrant_Fdw(InternalGrant *istmt)
+{
+ Relation relation;
+ ListCell *cell;
+
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ istmt->privileges = ACL_ALL_RIGHTS_FDW;
+
+ relation = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid fdwid = lfirst_oid(cell);
+ Form_pg_foreign_data_wrapper pg_fdw_tuple;
+ Datum aclDatum;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *old_acl;
+ Acl *new_acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple tuple;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_foreign_data_wrapper];
+ bool nulls[Natts_pg_foreign_data_wrapper];
+ bool replaces[Natts_pg_foreign_data_wrapper];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+
+ tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID,
+ ObjectIdGetDatum(fdwid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
+
+ pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_fdw_tuple->fdwowner;
+ aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
+ Anum_pg_foreign_data_wrapper_fdwacl,
+ &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(OBJECT_FDW, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), istmt->privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, istmt->privileges,
+ fdwid, grantorId, OBJECT_FDW,
+ NameStr(pg_fdw_tuple->fdwname),
+ 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option, istmt->behavior,
+ istmt->grantees, this_privileges,
+ grantorId, ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
+ values[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
+ nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(fdwid, ForeignDataWrapperRelationId, 0,
+ new_acl);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(ForeignDataWrapperRelationId,
+ pg_fdw_tuple->oid, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ ReleaseSysCache(tuple);
+
+ pfree(new_acl);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(relation, RowExclusiveLock);
+}
+
+static void
+ExecGrant_ForeignServer(InternalGrant *istmt)
+{
+ Relation relation;
+ ListCell *cell;
+
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
+
+ relation = table_open(ForeignServerRelationId, RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid srvid = lfirst_oid(cell);
+ Form_pg_foreign_server pg_server_tuple;
+ Datum aclDatum;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *old_acl;
+ Acl *new_acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple tuple;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_foreign_server];
+ bool nulls[Natts_pg_foreign_server];
+ bool replaces[Natts_pg_foreign_server];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+
+ tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srvid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for foreign server %u", srvid);
+
+ pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_server_tuple->srvowner;
+ aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
+ Anum_pg_foreign_server_srvacl,
+ &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(OBJECT_FOREIGN_SERVER, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), istmt->privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, istmt->privileges,
+ srvid, grantorId, OBJECT_FOREIGN_SERVER,
+ NameStr(pg_server_tuple->srvname),
+ 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option, istmt->behavior,
+ istmt->grantees, this_privileges,
+ grantorId, ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_foreign_server_srvacl - 1] = true;
+ values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
+ nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(srvid, ForeignServerRelationId, 0, new_acl);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(ForeignServerRelationId,
+ pg_server_tuple->oid, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ ReleaseSysCache(tuple);
+
+ pfree(new_acl);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(relation, RowExclusiveLock);
+}
+
+static void
+ExecGrant_Function(InternalGrant *istmt)
+{
+ Relation relation;
+ ListCell *cell;
+
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ istmt->privileges = ACL_ALL_RIGHTS_FUNCTION;
+
+ relation = table_open(ProcedureRelationId, RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid funcId = lfirst_oid(cell);
+ Form_pg_proc pg_proc_tuple;
+ Datum aclDatum;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *old_acl;
+ Acl *new_acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple tuple;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_proc];
+ bool nulls[Natts_pg_proc];
+ bool replaces[Natts_pg_proc];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", funcId);
+
+ pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_proc_tuple->proowner;
+ aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
+ &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(OBJECT_FUNCTION, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), istmt->privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, istmt->privileges,
+ funcId, grantorId, OBJECT_FUNCTION,
+ NameStr(pg_proc_tuple->proname),
+ 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option, istmt->behavior,
+ istmt->grantees, this_privileges,
+ grantorId, ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_proc_proacl - 1] = true;
+ values[Anum_pg_proc_proacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
+ nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(funcId, ProcedureRelationId, 0, new_acl);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(ProcedureRelationId, funcId, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ ReleaseSysCache(tuple);
+
+ pfree(new_acl);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(relation, RowExclusiveLock);
+}
+
+static void
+ExecGrant_Language(InternalGrant *istmt)
+{
+ Relation relation;
+ ListCell *cell;
+
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ istmt->privileges = ACL_ALL_RIGHTS_LANGUAGE;
+
+ relation = table_open(LanguageRelationId, RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid langId = lfirst_oid(cell);
+ Form_pg_language pg_language_tuple;
+ Datum aclDatum;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *old_acl;
+ Acl *new_acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple tuple;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_language];
+ bool nulls[Natts_pg_language];
+ bool replaces[Natts_pg_language];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+
+ tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(langId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for language %u", langId);
+
+ pg_language_tuple = (Form_pg_language) GETSTRUCT(tuple);
+
+ if (!pg_language_tuple->lanpltrusted)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("language \"%s\" is not trusted",
+ NameStr(pg_language_tuple->lanname)),
+ errdetail("GRANT and REVOKE are not allowed on untrusted languages, "
+ "because only superusers can use untrusted languages.")));
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_language_tuple->lanowner;
+ aclDatum = SysCacheGetAttr(LANGNAME, tuple, Anum_pg_language_lanacl,
+ &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(OBJECT_LANGUAGE, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), istmt->privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, istmt->privileges,
+ langId, grantorId, OBJECT_LANGUAGE,
+ NameStr(pg_language_tuple->lanname),
+ 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option, istmt->behavior,
+ istmt->grantees, this_privileges,
+ grantorId, ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_language_lanacl - 1] = true;
+ values[Anum_pg_language_lanacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
+ nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(LanguageRelationId, pg_language_tuple->oid, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ ReleaseSysCache(tuple);
+
+ pfree(new_acl);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(relation, RowExclusiveLock);
+}
+
+static void
+ExecGrant_Largeobject(InternalGrant *istmt)
+{
+ Relation relation;
+ ListCell *cell;
+
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ istmt->privileges = ACL_ALL_RIGHTS_LARGEOBJECT;
+
+ relation = table_open(LargeObjectMetadataRelationId,
+ RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid loid = lfirst_oid(cell);
+ Form_pg_largeobject_metadata form_lo_meta;
+ char loname[NAMEDATALEN];
+ Datum aclDatum;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *old_acl;
+ Acl *new_acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_largeobject_metadata];
+ bool nulls[Natts_pg_largeobject_metadata];
+ bool replaces[Natts_pg_largeobject_metadata];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+ ScanKeyData entry[1];
+ SysScanDesc scan;
+ HeapTuple tuple;
+
+ /* There's no syscache for pg_largeobject_metadata */
+ ScanKeyInit(&entry[0],
+ Anum_pg_largeobject_metadata_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(loid));
+
+ scan = systable_beginscan(relation,
+ LargeObjectMetadataOidIndexId, true,
+ NULL, 1, entry);
+
+ tuple = systable_getnext(scan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "could not find tuple for large object %u", loid);
+
+ form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(tuple);
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = form_lo_meta->lomowner;
+ aclDatum = heap_getattr(tuple,
+ Anum_pg_largeobject_metadata_lomacl,
+ RelationGetDescr(relation), &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), istmt->privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages.
+ */
+ snprintf(loname, sizeof(loname), "large object %u", loid);
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, istmt->privileges,
+ loid, grantorId, OBJECT_LARGEOBJECT,
+ loname, 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option, istmt->behavior,
+ istmt->grantees, this_privileges,
+ grantorId, ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
+ values[Anum_pg_largeobject_metadata_lomacl - 1]
+ = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation),
+ values, nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(loid, LargeObjectRelationId, 0, new_acl);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(LargeObjectRelationId,
+ form_lo_meta->oid, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ systable_endscan(scan);
+
+ pfree(new_acl);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(relation, RowExclusiveLock);
+}
+
+static void
+ExecGrant_Namespace(InternalGrant *istmt)
+{
+ Relation relation;
+ ListCell *cell;
+
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ istmt->privileges = ACL_ALL_RIGHTS_SCHEMA;
+
+ relation = table_open(NamespaceRelationId, RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid nspid = lfirst_oid(cell);
+ Form_pg_namespace pg_namespace_tuple;
+ Datum aclDatum;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *old_acl;
+ Acl *new_acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple tuple;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_namespace];
+ bool nulls[Natts_pg_namespace];
+ bool replaces[Natts_pg_namespace];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+
+ tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for namespace %u", nspid);
+
+ pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_namespace_tuple->nspowner;
+ aclDatum = SysCacheGetAttr(NAMESPACENAME, tuple,
+ Anum_pg_namespace_nspacl,
+ &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(OBJECT_SCHEMA, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), istmt->privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, istmt->privileges,
+ nspid, grantorId, OBJECT_SCHEMA,
+ NameStr(pg_namespace_tuple->nspname),
+ 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option, istmt->behavior,
+ istmt->grantees, this_privileges,
+ grantorId, ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_namespace_nspacl - 1] = true;
+ values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
+ nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(NamespaceRelationId, pg_namespace_tuple->oid, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ ReleaseSysCache(tuple);
+
+ pfree(new_acl);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(relation, RowExclusiveLock);
+}
+
+static void
+ExecGrant_Tablespace(InternalGrant *istmt)
+{
+ Relation relation;
+ ListCell *cell;
+
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ istmt->privileges = ACL_ALL_RIGHTS_TABLESPACE;
+
+ relation = table_open(TableSpaceRelationId, RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid tblId = lfirst_oid(cell);
+ Form_pg_tablespace pg_tablespace_tuple;
+ Datum aclDatum;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *old_acl;
+ Acl *new_acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_tablespace];
+ bool nulls[Natts_pg_tablespace];
+ bool replaces[Natts_pg_tablespace];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+ HeapTuple tuple;
+
+ /* Search syscache for pg_tablespace */
+ tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(tblId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for tablespace %u", tblId);
+
+ pg_tablespace_tuple = (Form_pg_tablespace) GETSTRUCT(tuple);
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_tablespace_tuple->spcowner;
+ aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl,
+ RelationGetDescr(relation), &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(OBJECT_TABLESPACE, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), istmt->privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, istmt->privileges,
+ tblId, grantorId, OBJECT_TABLESPACE,
+ NameStr(pg_tablespace_tuple->spcname),
+ 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option, istmt->behavior,
+ istmt->grantees, this_privileges,
+ grantorId, ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_tablespace_spcacl - 1] = true;
+ values[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
+ nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(TableSpaceRelationId, tblId, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ ReleaseSysCache(tuple);
+ pfree(new_acl);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(relation, RowExclusiveLock);
+}
+
+static void
+ExecGrant_Type(InternalGrant *istmt)
+{
+ Relation relation;
+ ListCell *cell;
+
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ istmt->privileges = ACL_ALL_RIGHTS_TYPE;
+
+ relation = table_open(TypeRelationId, RowExclusiveLock);
+
+ foreach(cell, istmt->objects)
+ {
+ Oid typId = lfirst_oid(cell);
+ Form_pg_type pg_type_tuple;
+ Datum aclDatum;
+ bool isNull;
+ AclMode avail_goptions;
+ AclMode this_privileges;
+ Acl *old_acl;
+ Acl *new_acl;
+ Oid grantorId;
+ Oid ownerId;
+ HeapTuple newtuple;
+ Datum values[Natts_pg_type];
+ bool nulls[Natts_pg_type];
+ bool replaces[Natts_pg_type];
+ int noldmembers;
+ int nnewmembers;
+ Oid *oldmembers;
+ Oid *newmembers;
+ HeapTuple tuple;
+
+ /* Search syscache for pg_type */
+ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for type %u", typId);
+
+ pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple);
+
+ if (pg_type_tuple->typelem != 0 && pg_type_tuple->typlen == -1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("cannot set privileges of array types"),
+ errhint("Set the privileges of the element type instead.")));
+
+ /* Used GRANT DOMAIN on a non-domain? */
+ if (istmt->objtype == OBJECT_DOMAIN &&
+ pg_type_tuple->typtype != TYPTYPE_DOMAIN)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a domain",
+ NameStr(pg_type_tuple->typname))));
+
+ /*
+ * Get owner ID and working copy of existing ACL. If there's no ACL,
+ * substitute the proper default.
+ */
+ ownerId = pg_type_tuple->typowner;
+ aclDatum = heap_getattr(tuple, Anum_pg_type_typacl,
+ RelationGetDescr(relation), &isNull);
+ if (isNull)
+ {
+ old_acl = acldefault(istmt->objtype, ownerId);
+ /* There are no old member roles according to the catalogs */
+ noldmembers = 0;
+ oldmembers = NULL;
+ }
+ else
+ {
+ old_acl = DatumGetAclPCopy(aclDatum);
+ /* Get the roles mentioned in the existing ACL */
+ noldmembers = aclmembers(old_acl, &oldmembers);
+ }
+
+ /* Determine ID to do the grant as, and available grant options */
+ select_best_grantor(GetUserId(), istmt->privileges,
+ old_acl, ownerId,
+ &grantorId, &avail_goptions);
+
+ /*
+ * Restrict the privileges to what we can actually grant, and emit the
+ * standards-mandated warning and error messages.
+ */
+ this_privileges =
+ restrict_and_check_grant(istmt->is_grant, avail_goptions,
+ istmt->all_privs, istmt->privileges,
+ typId, grantorId, OBJECT_TYPE,
+ NameStr(pg_type_tuple->typname),
+ 0, NULL);
+
+ /*
+ * Generate new ACL.
+ */
+ new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
+ istmt->grant_option, istmt->behavior,
+ istmt->grantees, this_privileges,
+ grantorId, ownerId);
+
+ /*
+ * We need the members of both old and new ACLs so we can correct the
+ * shared dependency information.
+ */
+ nnewmembers = aclmembers(new_acl, &newmembers);
+
+ /* finished building new ACL value, now insert it */
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_type_typacl - 1] = true;
+ values[Anum_pg_type_typacl - 1] = PointerGetDatum(new_acl);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
+ nulls, replaces);
+
+ CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
+
+ /* Update initial privileges for extensions */
+ recordExtensionInitPriv(typId, TypeRelationId, 0, new_acl);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(TypeRelationId, typId, 0,
+ ownerId,
+ noldmembers, oldmembers,
+ nnewmembers, newmembers);
+
+ ReleaseSysCache(tuple);
+ pfree(new_acl);
+
+ /* prevent error when processing duplicate objects */
+ CommandCounterIncrement();
+ }
+
+ table_close(relation, RowExclusiveLock);
+}
+
+
+static AclMode
+string_to_privilege(const char *privname)
+{
+ if (strcmp(privname, "insert") == 0)
+ return ACL_INSERT;
+ if (strcmp(privname, "select") == 0)
+ return ACL_SELECT;
+ if (strcmp(privname, "update") == 0)
+ return ACL_UPDATE;
+ if (strcmp(privname, "delete") == 0)
+ return ACL_DELETE;
+ if (strcmp(privname, "truncate") == 0)
+ return ACL_TRUNCATE;
+ if (strcmp(privname, "references") == 0)
+ return ACL_REFERENCES;
+ if (strcmp(privname, "trigger") == 0)
+ return ACL_TRIGGER;
+ if (strcmp(privname, "execute") == 0)
+ return ACL_EXECUTE;
+ if (strcmp(privname, "usage") == 0)
+ return ACL_USAGE;
+ if (strcmp(privname, "create") == 0)
+ return ACL_CREATE;
+ if (strcmp(privname, "temporary") == 0)
+ return ACL_CREATE_TEMP;
+ if (strcmp(privname, "temp") == 0)
+ return ACL_CREATE_TEMP;
+ if (strcmp(privname, "connect") == 0)
+ return ACL_CONNECT;
+ if (strcmp(privname, "rule") == 0)
+ return 0; /* ignore old RULE privileges */
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized privilege type \"%s\"", privname)));
+ return 0; /* appease compiler */
+}
+
+static const char *
+privilege_to_string(AclMode privilege)
+{
+ switch (privilege)
+ {
+ case ACL_INSERT:
+ return "INSERT";
+ case ACL_SELECT:
+ return "SELECT";
+ case ACL_UPDATE:
+ return "UPDATE";
+ case ACL_DELETE:
+ return "DELETE";
+ case ACL_TRUNCATE:
+ return "TRUNCATE";
+ case ACL_REFERENCES:
+ return "REFERENCES";
+ case ACL_TRIGGER:
+ return "TRIGGER";
+ case ACL_EXECUTE:
+ return "EXECUTE";
+ case ACL_USAGE:
+ return "USAGE";
+ case ACL_CREATE:
+ return "CREATE";
+ case ACL_CREATE_TEMP:
+ return "TEMP";
+ case ACL_CONNECT:
+ return "CONNECT";
+ default:
+ elog(ERROR, "unrecognized privilege: %d", (int) privilege);
+ }
+ return NULL; /* appease compiler */
+}
+
+/*
+ * Standardized reporting of aclcheck permissions failures.
+ *
+ * Note: we do not double-quote the %s's below, because many callers
+ * supply strings that might be already quoted.
+ */
+void
+aclcheck_error(AclResult aclerr, ObjectType objtype,
+ const char *objectname)
+{
+ switch (aclerr)
+ {
+ case ACLCHECK_OK:
+ /* no error, so return to caller */
+ break;
+ case ACLCHECK_NO_PRIV:
+ {
+ const char *msg = "???";
+
+ switch (objtype)
+ {
+ case OBJECT_AGGREGATE:
+ msg = gettext_noop("permission denied for aggregate %s");
+ break;
+ case OBJECT_COLLATION:
+ msg = gettext_noop("permission denied for collation %s");
+ break;
+ case OBJECT_COLUMN:
+ msg = gettext_noop("permission denied for column %s");
+ break;
+ case OBJECT_CONVERSION:
+ msg = gettext_noop("permission denied for conversion %s");
+ break;
+ case OBJECT_DATABASE:
+ msg = gettext_noop("permission denied for database %s");
+ break;
+ case OBJECT_DOMAIN:
+ msg = gettext_noop("permission denied for domain %s");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ msg = gettext_noop("permission denied for event trigger %s");
+ break;
+ case OBJECT_EXTENSION:
+ msg = gettext_noop("permission denied for extension %s");
+ break;
+ case OBJECT_FDW:
+ msg = gettext_noop("permission denied for foreign-data wrapper %s");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ msg = gettext_noop("permission denied for foreign server %s");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ msg = gettext_noop("permission denied for foreign table %s");
+ break;
+ case OBJECT_FUNCTION:
+ msg = gettext_noop("permission denied for function %s");
+ break;
+ case OBJECT_INDEX:
+ msg = gettext_noop("permission denied for index %s");
+ break;
+ case OBJECT_LANGUAGE:
+ msg = gettext_noop("permission denied for language %s");
+ break;
+ case OBJECT_LARGEOBJECT:
+ msg = gettext_noop("permission denied for large object %s");
+ break;
+ case OBJECT_MATVIEW:
+ msg = gettext_noop("permission denied for materialized view %s");
+ break;
+ case OBJECT_OPCLASS:
+ msg = gettext_noop("permission denied for operator class %s");
+ break;
+ case OBJECT_OPERATOR:
+ msg = gettext_noop("permission denied for operator %s");
+ break;
+ case OBJECT_OPFAMILY:
+ msg = gettext_noop("permission denied for operator family %s");
+ break;
+ case OBJECT_POLICY:
+ msg = gettext_noop("permission denied for policy %s");
+ break;
+ case OBJECT_PROCEDURE:
+ msg = gettext_noop("permission denied for procedure %s");
+ break;
+ case OBJECT_PUBLICATION:
+ msg = gettext_noop("permission denied for publication %s");
+ break;
+ case OBJECT_ROUTINE:
+ msg = gettext_noop("permission denied for routine %s");
+ break;
+ case OBJECT_SCHEMA:
+ msg = gettext_noop("permission denied for schema %s");
+ break;
+ case OBJECT_SEQUENCE:
+ msg = gettext_noop("permission denied for sequence %s");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ msg = gettext_noop("permission denied for statistics object %s");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ msg = gettext_noop("permission denied for subscription %s");
+ break;
+ case OBJECT_TABLE:
+ msg = gettext_noop("permission denied for table %s");
+ break;
+ case OBJECT_TABLESPACE:
+ msg = gettext_noop("permission denied for tablespace %s");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ msg = gettext_noop("permission denied for text search configuration %s");
+ break;
+ case OBJECT_TSDICTIONARY:
+ msg = gettext_noop("permission denied for text search dictionary %s");
+ break;
+ case OBJECT_TYPE:
+ msg = gettext_noop("permission denied for type %s");
+ break;
+ case OBJECT_VIEW:
+ msg = gettext_noop("permission denied for view %s");
+ break;
+ /* these currently aren't used */
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_AMOP:
+ case OBJECT_AMPROC:
+ case OBJECT_ATTRIBUTE:
+ case OBJECT_CAST:
+ case OBJECT_DEFAULT:
+ case OBJECT_DEFACL:
+ case OBJECT_DOMCONSTRAINT:
+ case OBJECT_PUBLICATION_REL:
+ case OBJECT_ROLE:
+ case OBJECT_RULE:
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_TRANSFORM:
+ case OBJECT_TRIGGER:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_USER_MAPPING:
+ elog(ERROR, "unsupported object type %d", objtype);
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg(msg, objectname)));
+ break;
+ }
+ case ACLCHECK_NOT_OWNER:
+ {
+ const char *msg = "???";
+
+ switch (objtype)
+ {
+ case OBJECT_AGGREGATE:
+ msg = gettext_noop("must be owner of aggregate %s");
+ break;
+ case OBJECT_COLLATION:
+ msg = gettext_noop("must be owner of collation %s");
+ break;
+ case OBJECT_CONVERSION:
+ msg = gettext_noop("must be owner of conversion %s");
+ break;
+ case OBJECT_DATABASE:
+ msg = gettext_noop("must be owner of database %s");
+ break;
+ case OBJECT_DOMAIN:
+ msg = gettext_noop("must be owner of domain %s");
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ msg = gettext_noop("must be owner of event trigger %s");
+ break;
+ case OBJECT_EXTENSION:
+ msg = gettext_noop("must be owner of extension %s");
+ break;
+ case OBJECT_FDW:
+ msg = gettext_noop("must be owner of foreign-data wrapper %s");
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ msg = gettext_noop("must be owner of foreign server %s");
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ msg = gettext_noop("must be owner of foreign table %s");
+ break;
+ case OBJECT_FUNCTION:
+ msg = gettext_noop("must be owner of function %s");
+ break;
+ case OBJECT_INDEX:
+ msg = gettext_noop("must be owner of index %s");
+ break;
+ case OBJECT_LANGUAGE:
+ msg = gettext_noop("must be owner of language %s");
+ break;
+ case OBJECT_LARGEOBJECT:
+ msg = gettext_noop("must be owner of large object %s");
+ break;
+ case OBJECT_MATVIEW:
+ msg = gettext_noop("must be owner of materialized view %s");
+ break;
+ case OBJECT_OPCLASS:
+ msg = gettext_noop("must be owner of operator class %s");
+ break;
+ case OBJECT_OPERATOR:
+ msg = gettext_noop("must be owner of operator %s");
+ break;
+ case OBJECT_OPFAMILY:
+ msg = gettext_noop("must be owner of operator family %s");
+ break;
+ case OBJECT_PROCEDURE:
+ msg = gettext_noop("must be owner of procedure %s");
+ break;
+ case OBJECT_PUBLICATION:
+ msg = gettext_noop("must be owner of publication %s");
+ break;
+ case OBJECT_ROUTINE:
+ msg = gettext_noop("must be owner of routine %s");
+ break;
+ case OBJECT_SEQUENCE:
+ msg = gettext_noop("must be owner of sequence %s");
+ break;
+ case OBJECT_SUBSCRIPTION:
+ msg = gettext_noop("must be owner of subscription %s");
+ break;
+ case OBJECT_TABLE:
+ msg = gettext_noop("must be owner of table %s");
+ break;
+ case OBJECT_TYPE:
+ msg = gettext_noop("must be owner of type %s");
+ break;
+ case OBJECT_VIEW:
+ msg = gettext_noop("must be owner of view %s");
+ break;
+ case OBJECT_SCHEMA:
+ msg = gettext_noop("must be owner of schema %s");
+ break;
+ case OBJECT_STATISTIC_EXT:
+ msg = gettext_noop("must be owner of statistics object %s");
+ break;
+ case OBJECT_TABLESPACE:
+ msg = gettext_noop("must be owner of tablespace %s");
+ break;
+ case OBJECT_TSCONFIGURATION:
+ msg = gettext_noop("must be owner of text search configuration %s");
+ break;
+ case OBJECT_TSDICTIONARY:
+ msg = gettext_noop("must be owner of text search dictionary %s");
+ break;
+
+ /*
+ * Special cases: For these, the error message talks
+ * about "relation", because that's where the
+ * ownership is attached. See also
+ * check_object_ownership().
+ */
+ case OBJECT_COLUMN:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_TRIGGER:
+ msg = gettext_noop("must be owner of relation %s");
+ break;
+ /* these currently aren't used */
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_AMOP:
+ case OBJECT_AMPROC:
+ case OBJECT_ATTRIBUTE:
+ case OBJECT_CAST:
+ case OBJECT_DEFAULT:
+ case OBJECT_DEFACL:
+ case OBJECT_DOMCONSTRAINT:
+ case OBJECT_PUBLICATION_REL:
+ case OBJECT_ROLE:
+ case OBJECT_TRANSFORM:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_USER_MAPPING:
+ elog(ERROR, "unsupported object type %d", objtype);
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg(msg, objectname)));
+ break;
+ }
+ default:
+ elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
+ break;
+ }
+}
+
+
+void
+aclcheck_error_col(AclResult aclerr, ObjectType objtype,
+ const char *objectname, const char *colname)
+{
+ switch (aclerr)
+ {
+ case ACLCHECK_OK:
+ /* no error, so return to caller */
+ break;
+ case ACLCHECK_NO_PRIV:
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied for column \"%s\" of relation \"%s\"",
+ colname, objectname)));
+ break;
+ case ACLCHECK_NOT_OWNER:
+ /* relation msg is OK since columns don't have separate owners */
+ aclcheck_error(aclerr, objtype, objectname);
+ break;
+ default:
+ elog(ERROR, "unrecognized AclResult: %d", (int) aclerr);
+ break;
+ }
+}
+
+
+/*
+ * Special common handling for types: use element type instead of array type,
+ * and format nicely
+ */
+void
+aclcheck_error_type(AclResult aclerr, Oid typeOid)
+{
+ Oid element_type = get_element_type(typeOid);
+
+ aclcheck_error(aclerr, OBJECT_TYPE, format_type_be(element_type ? element_type : typeOid));
+}
+
+
+/*
+ * Relay for the various pg_*_mask routines depending on object kind
+ */
+static AclMode
+pg_aclmask(ObjectType objtype, Oid table_oid, AttrNumber attnum, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ switch (objtype)
+ {
+ case OBJECT_COLUMN:
+ return
+ pg_class_aclmask(table_oid, roleid, mask, how) |
+ pg_attribute_aclmask(table_oid, attnum, roleid, mask, how);
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ return pg_class_aclmask(table_oid, roleid, mask, how);
+ case OBJECT_DATABASE:
+ return pg_database_aclmask(table_oid, roleid, mask, how);
+ case OBJECT_FUNCTION:
+ return pg_proc_aclmask(table_oid, roleid, mask, how);
+ case OBJECT_LANGUAGE:
+ return pg_language_aclmask(table_oid, roleid, mask, how);
+ case OBJECT_LARGEOBJECT:
+ return pg_largeobject_aclmask_snapshot(table_oid, roleid,
+ mask, how, NULL);
+ case OBJECT_SCHEMA:
+ return pg_namespace_aclmask(table_oid, roleid, mask, how);
+ case OBJECT_STATISTIC_EXT:
+ elog(ERROR, "grantable rights not supported for statistics objects");
+ /* not reached, but keep compiler quiet */
+ return ACL_NO_RIGHTS;
+ case OBJECT_TABLESPACE:
+ return pg_tablespace_aclmask(table_oid, roleid, mask, how);
+ case OBJECT_FDW:
+ return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
+ case OBJECT_FOREIGN_SERVER:
+ return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
+ case OBJECT_EVENT_TRIGGER:
+ elog(ERROR, "grantable rights not supported for event triggers");
+ /* not reached, but keep compiler quiet */
+ return ACL_NO_RIGHTS;
+ case OBJECT_TYPE:
+ return pg_type_aclmask(table_oid, roleid, mask, how);
+ default:
+ elog(ERROR, "unrecognized objtype: %d",
+ (int) objtype);
+ /* not reached, but keep compiler quiet */
+ return ACL_NO_RIGHTS;
+ }
+}
+
+
+/* ****************************************************************
+ * Exported routines for examining a user's privileges for various objects
+ *
+ * See aclmask() for a description of the common API for these functions.
+ *
+ * Note: we give lookup failure the full ereport treatment because the
+ * has_xxx_privilege() family of functions allow users to pass any random
+ * OID to these functions.
+ * ****************************************************************
+ */
+
+/*
+ * Exported routine for examining a user's privileges for a column
+ *
+ * Note: this considers only privileges granted specifically on the column.
+ * It is caller's responsibility to take relation-level privileges into account
+ * as appropriate. (For the same reason, we have no special case for
+ * superuser-ness here.)
+ */
+AclMode
+pg_attribute_aclmask(Oid table_oid, AttrNumber attnum, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple classTuple;
+ HeapTuple attTuple;
+ Form_pg_class classForm;
+ Form_pg_attribute attributeForm;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ /*
+ * First, get the column's ACL from its pg_attribute entry
+ */
+ attTuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(table_oid),
+ Int16GetDatum(attnum));
+ if (!HeapTupleIsValid(attTuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("attribute %d of relation with OID %u does not exist",
+ attnum, table_oid)));
+ attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
+
+ /* Throw error on dropped columns, too */
+ if (attributeForm->attisdropped)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("attribute %d of relation with OID %u does not exist",
+ attnum, table_oid)));
+
+ aclDatum = SysCacheGetAttr(ATTNUM, attTuple, Anum_pg_attribute_attacl,
+ &isNull);
+
+ /*
+ * Here we hard-wire knowledge that the default ACL for a column grants no
+ * privileges, so that we can fall out quickly in the very common case
+ * where attacl is null.
+ */
+ if (isNull)
+ {
+ ReleaseSysCache(attTuple);
+ return 0;
+ }
+
+ /*
+ * Must get the relation's ownerId from pg_class. Since we already found
+ * a pg_attribute entry, the only likely reason for this to fail is that a
+ * concurrent DROP of the relation committed since then (which could only
+ * happen if we don't have lock on the relation). We prefer to report "no
+ * privileges" rather than failing in such a case, so as to avoid unwanted
+ * failures in has_column_privilege() tests.
+ */
+ classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
+ if (!HeapTupleIsValid(classTuple))
+ {
+ ReleaseSysCache(attTuple);
+ return 0;
+ }
+ classForm = (Form_pg_class) GETSTRUCT(classTuple);
+
+ ownerId = classForm->relowner;
+
+ ReleaseSysCache(classTuple);
+
+ /* detoast column's ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(attTuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a table
+ */
+AclMode
+pg_class_aclmask(Oid table_oid, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple tuple;
+ Form_pg_class classForm;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ /*
+ * Must get the relation's tuple from pg_class
+ */
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("relation with OID %u does not exist",
+ table_oid)));
+ classForm = (Form_pg_class) GETSTRUCT(tuple);
+
+ /*
+ * Deny anyone permission to update a system catalog unless
+ * pg_authid.rolsuper is set.
+ *
+ * As of 7.4 we have some updatable system views; those shouldn't be
+ * protected in this way. Assume the view rules can take care of
+ * themselves. ACL_USAGE is if we ever have system sequences.
+ */
+ if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE)) &&
+ IsSystemClass(table_oid, classForm) &&
+ classForm->relkind != RELKIND_VIEW &&
+ !superuser_arg(roleid))
+ mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE | ACL_USAGE);
+
+ /*
+ * Otherwise, superusers bypass all permission-checking.
+ */
+ if (superuser_arg(roleid))
+ {
+ ReleaseSysCache(tuple);
+ return mask;
+ }
+
+ /*
+ * Normal case: get the relation's ACL from pg_class
+ */
+ ownerId = classForm->relowner;
+
+ aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
+ &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ switch (classForm->relkind)
+ {
+ case RELKIND_SEQUENCE:
+ acl = acldefault(OBJECT_SEQUENCE, ownerId);
+ break;
+ default:
+ acl = acldefault(OBJECT_TABLE, ownerId);
+ break;
+ }
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast rel's ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a database
+ */
+AclMode
+pg_database_aclmask(Oid db_oid, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return mask;
+
+ /*
+ * Get the database's ACL from pg_database
+ */
+ tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_DATABASE),
+ errmsg("database with OID %u does not exist", db_oid)));
+
+ ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
+
+ aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl,
+ &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(OBJECT_DATABASE, ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a function
+ */
+AclMode
+pg_proc_aclmask(Oid proc_oid, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return mask;
+
+ /*
+ * Get the function's ACL from pg_proc
+ */
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("function with OID %u does not exist", proc_oid)));
+
+ ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
+
+ aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
+ &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(OBJECT_FUNCTION, ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a language
+ */
+AclMode
+pg_language_aclmask(Oid lang_oid, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return mask;
+
+ /*
+ * Get the language's ACL from pg_language
+ */
+ tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lang_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("language with OID %u does not exist", lang_oid)));
+
+ ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
+
+ aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
+ &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(OBJECT_LANGUAGE, ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a largeobject
+ *
+ * When a large object is opened for reading, it is opened relative to the
+ * caller's snapshot, but when it is opened for writing, a current
+ * MVCC snapshot will be used. See doc/src/sgml/lobj.sgml. This function
+ * takes a snapshot argument so that the permissions check can be made
+ * relative to the same snapshot that will be used to read the underlying
+ * data. The caller will actually pass NULL for an instantaneous MVCC
+ * snapshot, since all we do with the snapshot argument is pass it through
+ * to systable_beginscan().
+ */
+AclMode
+pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
+ AclMode mask, AclMaskHow how,
+ Snapshot snapshot)
+{
+ AclMode result;
+ Relation pg_lo_meta;
+ ScanKeyData entry[1];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return mask;
+
+ /*
+ * Get the largeobject's ACL from pg_largeobject_metadata
+ */
+ pg_lo_meta = table_open(LargeObjectMetadataRelationId,
+ AccessShareLock);
+
+ ScanKeyInit(&entry[0],
+ Anum_pg_largeobject_metadata_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(lobj_oid));
+
+ scan = systable_beginscan(pg_lo_meta,
+ LargeObjectMetadataOidIndexId, true,
+ snapshot, 1, entry);
+
+ tuple = systable_getnext(scan);
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("large object %u does not exist", lobj_oid)));
+
+ ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
+
+ aclDatum = heap_getattr(tuple, Anum_pg_largeobject_metadata_lomacl,
+ RelationGetDescr(pg_lo_meta), &isNull);
+
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(OBJECT_LARGEOBJECT, ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ systable_endscan(scan);
+
+ table_close(pg_lo_meta, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a namespace
+ */
+AclMode
+pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return mask;
+
+ /*
+ * If we have been assigned this namespace as a temp namespace, check to
+ * make sure we have CREATE TEMP permission on the database, and if so act
+ * as though we have all standard (but not GRANT OPTION) permissions on
+ * the namespace. If we don't have CREATE TEMP, act as though we have
+ * only USAGE (and not CREATE) rights.
+ *
+ * This may seem redundant given the check in InitTempTableNamespace, but
+ * it really isn't since current user ID may have changed since then. The
+ * upshot of this behavior is that a SECURITY DEFINER function can create
+ * temp tables that can then be accessed (if permission is granted) by
+ * code in the same session that doesn't have permissions to create temp
+ * tables.
+ *
+ * XXX Would it be safe to ereport a special error message as
+ * InitTempTableNamespace does? Returning zero here means we'll get a
+ * generic "permission denied for schema pg_temp_N" message, which is not
+ * remarkably user-friendly.
+ */
+ if (isTempNamespace(nsp_oid))
+ {
+ if (pg_database_aclcheck(MyDatabaseId, roleid,
+ ACL_CREATE_TEMP) == ACLCHECK_OK)
+ return mask & ACL_ALL_RIGHTS_SCHEMA;
+ else
+ return mask & ACL_USAGE;
+ }
+
+ /*
+ * Get the schema's ACL from pg_namespace
+ */
+ tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_SCHEMA),
+ errmsg("schema with OID %u does not exist", nsp_oid)));
+
+ ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
+
+ aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple, Anum_pg_namespace_nspacl,
+ &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(OBJECT_SCHEMA, ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a tablespace
+ */
+AclMode
+pg_tablespace_aclmask(Oid spc_oid, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return mask;
+
+ /*
+ * Get the tablespace's ACL from pg_tablespace
+ */
+ tuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("tablespace with OID %u does not exist", spc_oid)));
+
+ ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner;
+
+ aclDatum = SysCacheGetAttr(TABLESPACEOID, tuple,
+ Anum_pg_tablespace_spcacl,
+ &isNull);
+
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(OBJECT_TABLESPACE, ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a foreign
+ * data wrapper
+ */
+AclMode
+pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ Form_pg_foreign_data_wrapper fdwForm;
+
+ /* Bypass permission checks for superusers */
+ if (superuser_arg(roleid))
+ return mask;
+
+ /*
+ * Must get the FDW's tuple from pg_foreign_data_wrapper
+ */
+ tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(fdw_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("foreign-data wrapper with OID %u does not exist",
+ fdw_oid)));
+ fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
+
+ /*
+ * Normal case: get the FDW's ACL from pg_foreign_data_wrapper
+ */
+ ownerId = fdwForm->fdwowner;
+
+ aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
+ Anum_pg_foreign_data_wrapper_fdwacl, &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(OBJECT_FDW, ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast rel's ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a foreign
+ * server.
+ */
+AclMode
+pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
+ AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ Form_pg_foreign_server srvForm;
+
+ /* Bypass permission checks for superusers */
+ if (superuser_arg(roleid))
+ return mask;
+
+ /*
+ * Must get the FDW's tuple from pg_foreign_data_wrapper
+ */
+ tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("foreign server with OID %u does not exist",
+ srv_oid)));
+ srvForm = (Form_pg_foreign_server) GETSTRUCT(tuple);
+
+ /*
+ * Normal case: get the foreign server's ACL from pg_foreign_server
+ */
+ ownerId = srvForm->srvowner;
+
+ aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
+ Anum_pg_foreign_server_srvacl, &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(OBJECT_FOREIGN_SERVER, ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast rel's ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for examining a user's privileges for a type.
+ */
+AclMode
+pg_type_aclmask(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how)
+{
+ AclMode result;
+ HeapTuple tuple;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
+ Oid ownerId;
+
+ Form_pg_type typeForm;
+
+ /* Bypass permission checks for superusers */
+ if (superuser_arg(roleid))
+ return mask;
+
+ /*
+ * Must get the type's tuple from pg_type
+ */
+ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("type with OID %u does not exist",
+ type_oid)));
+ typeForm = (Form_pg_type) GETSTRUCT(tuple);
+
+ /*
+ * "True" array types don't manage permissions of their own; consult the
+ * element type instead.
+ */
+ if (OidIsValid(typeForm->typelem) && typeForm->typlen == -1)
+ {
+ Oid elttype_oid = typeForm->typelem;
+
+ ReleaseSysCache(tuple);
+
+ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(elttype_oid));
+ /* this case is not a user-facing error, so elog not ereport */
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for type %u", elttype_oid);
+ typeForm = (Form_pg_type) GETSTRUCT(tuple);
+ }
+
+ /*
+ * Now get the type's owner and ACL from the tuple
+ */
+ ownerId = typeForm->typowner;
+
+ aclDatum = SysCacheGetAttr(TYPEOID, tuple,
+ Anum_pg_type_typacl, &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL */
+ acl = acldefault(OBJECT_TYPE, ownerId);
+ aclDatum = (Datum) 0;
+ }
+ else
+ {
+ /* detoast rel's ACL if necessary */
+ acl = DatumGetAclP(aclDatum);
+ }
+
+ result = aclmask(acl, roleid, ownerId, mask, how);
+
+ /* if we have a detoasted copy, free it */
+ if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
+ pfree(acl);
+
+ ReleaseSysCache(tuple);
+
+ return result;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a column
+ *
+ * Returns ACLCHECK_OK if the user has any of the privileges identified by
+ * 'mode'; otherwise returns a suitable error code (in practice, always
+ * ACLCHECK_NO_PRIV).
+ *
+ * As with pg_attribute_aclmask, only privileges granted directly on the
+ * column are considered here.
+ */
+AclResult
+pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum,
+ Oid roleid, AclMode mode)
+{
+ if (pg_attribute_aclmask(table_oid, attnum, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to any/all columns
+ *
+ * If 'how' is ACLMASK_ANY, then returns ACLCHECK_OK if user has any of the
+ * privileges identified by 'mode' on any non-dropped column in the relation;
+ * otherwise returns a suitable error code (in practice, always
+ * ACLCHECK_NO_PRIV).
+ *
+ * If 'how' is ACLMASK_ALL, then returns ACLCHECK_OK if user has any of the
+ * privileges identified by 'mode' on each non-dropped column in the relation
+ * (and there must be at least one such column); otherwise returns a suitable
+ * error code (in practice, always ACLCHECK_NO_PRIV).
+ *
+ * As with pg_attribute_aclmask, only privileges granted directly on the
+ * column(s) are considered here.
+ *
+ * Note: system columns are not considered here; there are cases where that
+ * might be appropriate but there are also cases where it wouldn't.
+ */
+AclResult
+pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode,
+ AclMaskHow how)
+{
+ AclResult result;
+ HeapTuple classTuple;
+ Form_pg_class classForm;
+ AttrNumber nattrs;
+ AttrNumber curr_att;
+
+ /*
+ * Must fetch pg_class row to check number of attributes. As in
+ * pg_attribute_aclmask, we prefer to return "no privileges" instead of
+ * throwing an error if we get any unexpected lookup errors.
+ */
+ classTuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
+ if (!HeapTupleIsValid(classTuple))
+ return ACLCHECK_NO_PRIV;
+ classForm = (Form_pg_class) GETSTRUCT(classTuple);
+
+ nattrs = classForm->relnatts;
+
+ ReleaseSysCache(classTuple);
+
+ /*
+ * Initialize result in case there are no non-dropped columns. We want to
+ * report failure in such cases for either value of 'how'.
+ */
+ result = ACLCHECK_NO_PRIV;
+
+ for (curr_att = 1; curr_att <= nattrs; curr_att++)
+ {
+ HeapTuple attTuple;
+ AclMode attmask;
+
+ attTuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(table_oid),
+ Int16GetDatum(curr_att));
+ if (!HeapTupleIsValid(attTuple))
+ continue;
+
+ /* ignore dropped columns */
+ if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
+ {
+ ReleaseSysCache(attTuple);
+ continue;
+ }
+
+ /*
+ * Here we hard-wire knowledge that the default ACL for a column
+ * grants no privileges, so that we can fall out quickly in the very
+ * common case where attacl is null.
+ */
+ if (heap_attisnull(attTuple, Anum_pg_attribute_attacl, NULL))
+ attmask = 0;
+ else
+ attmask = pg_attribute_aclmask(table_oid, curr_att, roleid,
+ mode, ACLMASK_ANY);
+
+ ReleaseSysCache(attTuple);
+
+ if (attmask != 0)
+ {
+ result = ACLCHECK_OK;
+ if (how == ACLMASK_ANY)
+ break; /* succeed on any success */
+ }
+ else
+ {
+ result = ACLCHECK_NO_PRIV;
+ if (how == ACLMASK_ALL)
+ break; /* fail on any failure */
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a table
+ *
+ * Returns ACLCHECK_OK if the user has any of the privileges identified by
+ * 'mode'; otherwise returns a suitable error code (in practice, always
+ * ACLCHECK_NO_PRIV).
+ */
+AclResult
+pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
+{
+ if (pg_class_aclmask(table_oid, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a database
+ */
+AclResult
+pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
+{
+ if (pg_database_aclmask(db_oid, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a function
+ */
+AclResult
+pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
+{
+ if (pg_proc_aclmask(proc_oid, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a language
+ */
+AclResult
+pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode)
+{
+ if (pg_language_aclmask(lang_oid, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a largeobject
+ */
+AclResult
+pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid, AclMode mode,
+ Snapshot snapshot)
+{
+ if (pg_largeobject_aclmask_snapshot(lobj_oid, roleid, mode,
+ ACLMASK_ANY, snapshot) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a namespace
+ */
+AclResult
+pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
+{
+ if (pg_namespace_aclmask(nsp_oid, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a tablespace
+ */
+AclResult
+pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
+{
+ if (pg_tablespace_aclmask(spc_oid, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a foreign
+ * data wrapper
+ */
+AclResult
+pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
+{
+ if (pg_foreign_data_wrapper_aclmask(fdw_oid, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a foreign
+ * server
+ */
+AclResult
+pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
+{
+ if (pg_foreign_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Exported routine for checking a user's access privileges to a type
+ */
+AclResult
+pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
+{
+ if (pg_type_aclmask(type_oid, roleid, mode, ACLMASK_ANY) != 0)
+ return ACLCHECK_OK;
+ else
+ return ACLCHECK_NO_PRIV;
+}
+
+/*
+ * Ownership check for a relation (specified by OID).
+ */
+bool
+pg_class_ownercheck(Oid class_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(class_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("relation with OID %u does not exist", class_oid)));
+
+ ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a type (specified by OID).
+ */
+bool
+pg_type_ownercheck(Oid type_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("type with OID %u does not exist", type_oid)));
+
+ ownerId = ((Form_pg_type) GETSTRUCT(tuple))->typowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for an operator (specified by OID).
+ */
+bool
+pg_oper_ownercheck(Oid oper_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(oper_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("operator with OID %u does not exist", oper_oid)));
+
+ ownerId = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a function (specified by OID).
+ */
+bool
+pg_proc_ownercheck(Oid proc_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("function with OID %u does not exist", proc_oid)));
+
+ ownerId = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a procedural language (specified by OID)
+ */
+bool
+pg_language_ownercheck(Oid lan_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(lan_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("language with OID %u does not exist", lan_oid)));
+
+ ownerId = ((Form_pg_language) GETSTRUCT(tuple))->lanowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a largeobject (specified by OID)
+ *
+ * This is only used for operations like ALTER LARGE OBJECT that are always
+ * relative to an up-to-date snapshot.
+ */
+bool
+pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid)
+{
+ Relation pg_lo_meta;
+ ScanKeyData entry[1];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ /* There's no syscache for pg_largeobject_metadata */
+ pg_lo_meta = table_open(LargeObjectMetadataRelationId,
+ AccessShareLock);
+
+ ScanKeyInit(&entry[0],
+ Anum_pg_largeobject_metadata_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(lobj_oid));
+
+ scan = systable_beginscan(pg_lo_meta,
+ LargeObjectMetadataOidIndexId, true,
+ NULL, 1, entry);
+
+ tuple = systable_getnext(scan);
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("large object %u does not exist", lobj_oid)));
+
+ ownerId = ((Form_pg_largeobject_metadata) GETSTRUCT(tuple))->lomowner;
+
+ systable_endscan(scan);
+ table_close(pg_lo_meta, AccessShareLock);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a namespace (specified by OID).
+ */
+bool
+pg_namespace_ownercheck(Oid nsp_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nsp_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_SCHEMA),
+ errmsg("schema with OID %u does not exist", nsp_oid)));
+
+ ownerId = ((Form_pg_namespace) GETSTRUCT(tuple))->nspowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a tablespace (specified by OID).
+ */
+bool
+pg_tablespace_ownercheck(Oid spc_oid, Oid roleid)
+{
+ HeapTuple spctuple;
+ Oid spcowner;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ /* Search syscache for pg_tablespace */
+ spctuple = SearchSysCache1(TABLESPACEOID, ObjectIdGetDatum(spc_oid));
+ if (!HeapTupleIsValid(spctuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("tablespace with OID %u does not exist", spc_oid)));
+
+ spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner;
+
+ ReleaseSysCache(spctuple);
+
+ return has_privs_of_role(roleid, spcowner);
+}
+
+/*
+ * Ownership check for an operator class (specified by OID).
+ */
+bool
+pg_opclass_ownercheck(Oid opc_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opc_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("operator class with OID %u does not exist",
+ opc_oid)));
+
+ ownerId = ((Form_pg_opclass) GETSTRUCT(tuple))->opcowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for an operator family (specified by OID).
+ */
+bool
+pg_opfamily_ownercheck(Oid opf_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opf_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("operator family with OID %u does not exist",
+ opf_oid)));
+
+ ownerId = ((Form_pg_opfamily) GETSTRUCT(tuple))->opfowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a text search dictionary (specified by OID).
+ */
+bool
+pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dict_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("text search dictionary with OID %u does not exist",
+ dict_oid)));
+
+ ownerId = ((Form_pg_ts_dict) GETSTRUCT(tuple))->dictowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a text search configuration (specified by OID).
+ */
+bool
+pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfg_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("text search configuration with OID %u does not exist",
+ cfg_oid)));
+
+ ownerId = ((Form_pg_ts_config) GETSTRUCT(tuple))->cfgowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a foreign-data wrapper (specified by OID).
+ */
+bool
+pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID, ObjectIdGetDatum(srv_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("foreign-data wrapper with OID %u does not exist",
+ srv_oid)));
+
+ ownerId = ((Form_pg_foreign_data_wrapper) GETSTRUCT(tuple))->fdwowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a foreign server (specified by OID).
+ */
+bool
+pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(srv_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("foreign server with OID %u does not exist",
+ srv_oid)));
+
+ ownerId = ((Form_pg_foreign_server) GETSTRUCT(tuple))->srvowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for an event trigger (specified by OID).
+ */
+bool
+pg_event_trigger_ownercheck(Oid et_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(EVENTTRIGGEROID, ObjectIdGetDatum(et_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("event trigger with OID %u does not exist",
+ et_oid)));
+
+ ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a database (specified by OID).
+ */
+bool
+pg_database_ownercheck(Oid db_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid dba;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(db_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_DATABASE),
+ errmsg("database with OID %u does not exist", db_oid)));
+
+ dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, dba);
+}
+
+/*
+ * Ownership check for a collation (specified by OID).
+ */
+bool
+pg_collation_ownercheck(Oid coll_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(coll_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("collation with OID %u does not exist", coll_oid)));
+
+ ownerId = ((Form_pg_collation) GETSTRUCT(tuple))->collowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a conversion (specified by OID).
+ */
+bool
+pg_conversion_ownercheck(Oid conv_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conv_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("conversion with OID %u does not exist", conv_oid)));
+
+ ownerId = ((Form_pg_conversion) GETSTRUCT(tuple))->conowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for an extension (specified by OID).
+ */
+bool
+pg_extension_ownercheck(Oid ext_oid, Oid roleid)
+{
+ Relation pg_extension;
+ ScanKeyData entry[1];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ /* There's no syscache for pg_extension, so do it the hard way */
+ pg_extension = table_open(ExtensionRelationId, AccessShareLock);
+
+ ScanKeyInit(&entry[0],
+ Anum_pg_extension_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(ext_oid));
+
+ scan = systable_beginscan(pg_extension,
+ ExtensionOidIndexId, true,
+ NULL, 1, entry);
+
+ tuple = systable_getnext(scan);
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("extension with OID %u does not exist", ext_oid)));
+
+ ownerId = ((Form_pg_extension) GETSTRUCT(tuple))->extowner;
+
+ systable_endscan(scan);
+ table_close(pg_extension, AccessShareLock);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a publication (specified by OID).
+ */
+bool
+pg_publication_ownercheck(Oid pub_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pub_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication with OID %u does not exist", pub_oid)));
+
+ ownerId = ((Form_pg_publication) GETSTRUCT(tuple))->pubowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a subscription (specified by OID).
+ */
+bool
+pg_subscription_ownercheck(Oid sub_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(sub_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("subscription with OID %u does not exist", sub_oid)));
+
+ ownerId = ((Form_pg_subscription) GETSTRUCT(tuple))->subowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Ownership check for a statistics object (specified by OID).
+ */
+bool
+pg_statistics_object_ownercheck(Oid stat_oid, Oid roleid)
+{
+ HeapTuple tuple;
+ Oid ownerId;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ tuple = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(stat_oid));
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("statistics object with OID %u does not exist",
+ stat_oid)));
+
+ ownerId = ((Form_pg_statistic_ext) GETSTRUCT(tuple))->stxowner;
+
+ ReleaseSysCache(tuple);
+
+ return has_privs_of_role(roleid, ownerId);
+}
+
+/*
+ * Check whether specified role has CREATEROLE privilege (or is a superuser)
+ *
+ * Note: roles do not have owners per se; instead we use this test in
+ * places where an ownership-like permissions test is needed for a role.
+ * Be sure to apply it to the role trying to do the operation, not the
+ * role being operated on! Also note that this generally should not be
+ * considered enough privilege if the target role is a superuser.
+ * (We don't handle that consideration here because we want to give a
+ * separate error message for such cases, so the caller has to deal with it.)
+ */
+bool
+has_createrole_privilege(Oid roleid)
+{
+ bool result = false;
+ HeapTuple utup;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
+ if (HeapTupleIsValid(utup))
+ {
+ result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreaterole;
+ ReleaseSysCache(utup);
+ }
+ return result;
+}
+
+bool
+has_bypassrls_privilege(Oid roleid)
+{
+ bool result = false;
+ HeapTuple utup;
+
+ /* Superusers bypass all permission checking. */
+ if (superuser_arg(roleid))
+ return true;
+
+ utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
+ if (HeapTupleIsValid(utup))
+ {
+ result = ((Form_pg_authid) GETSTRUCT(utup))->rolbypassrls;
+ ReleaseSysCache(utup);
+ }
+ return result;
+}
+
+/*
+ * Fetch pg_default_acl entry for given role, namespace and object type
+ * (object type must be given in pg_default_acl's encoding).
+ * Returns NULL if no such entry.
+ */
+static Acl *
+get_default_acl_internal(Oid roleId, Oid nsp_oid, char objtype)
+{
+ Acl *result = NULL;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache3(DEFACLROLENSPOBJ,
+ ObjectIdGetDatum(roleId),
+ ObjectIdGetDatum(nsp_oid),
+ CharGetDatum(objtype));
+
+ if (HeapTupleIsValid(tuple))
+ {
+ Datum aclDatum;
+ bool isNull;
+
+ aclDatum = SysCacheGetAttr(DEFACLROLENSPOBJ, tuple,
+ Anum_pg_default_acl_defaclacl,
+ &isNull);
+ if (!isNull)
+ result = DatumGetAclPCopy(aclDatum);
+ ReleaseSysCache(tuple);
+ }
+
+ return result;
+}
+
+/*
+ * Get default permissions for newly created object within given schema
+ *
+ * Returns NULL if built-in system defaults should be used.
+ *
+ * If the result is not NULL, caller must call recordDependencyOnNewAcl
+ * once the OID of the new object is known.
+ */
+Acl *
+get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
+{
+ Acl *result;
+ Acl *glob_acl;
+ Acl *schema_acl;
+ Acl *def_acl;
+ char defaclobjtype;
+
+ /*
+ * Use NULL during bootstrap, since pg_default_acl probably isn't there
+ * yet.
+ */
+ if (IsBootstrapProcessingMode())
+ return NULL;
+
+ /* Check if object type is supported in pg_default_acl */
+ switch (objtype)
+ {
+ case OBJECT_TABLE:
+ defaclobjtype = DEFACLOBJ_RELATION;
+ break;
+
+ case OBJECT_SEQUENCE:
+ defaclobjtype = DEFACLOBJ_SEQUENCE;
+ break;
+
+ case OBJECT_FUNCTION:
+ defaclobjtype = DEFACLOBJ_FUNCTION;
+ break;
+
+ case OBJECT_TYPE:
+ defaclobjtype = DEFACLOBJ_TYPE;
+ break;
+
+ case OBJECT_SCHEMA:
+ defaclobjtype = DEFACLOBJ_NAMESPACE;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ /* Look up the relevant pg_default_acl entries */
+ glob_acl = get_default_acl_internal(ownerId, InvalidOid, defaclobjtype);
+ schema_acl = get_default_acl_internal(ownerId, nsp_oid, defaclobjtype);
+
+ /* Quick out if neither entry exists */
+ if (glob_acl == NULL && schema_acl == NULL)
+ return NULL;
+
+ /* We need to know the hard-wired default value, too */
+ def_acl = acldefault(objtype, ownerId);
+
+ /* If there's no global entry, substitute the hard-wired default */
+ if (glob_acl == NULL)
+ glob_acl = def_acl;
+
+ /* Merge in any per-schema privileges */
+ result = aclmerge(glob_acl, schema_acl, ownerId);
+
+ /*
+ * For efficiency, we want to return NULL if the result equals default.
+ * This requires sorting both arrays to get an accurate comparison.
+ */
+ aclitemsort(result);
+ aclitemsort(def_acl);
+ if (aclequal(result, def_acl))
+ result = NULL;
+
+ return result;
+}
+
+/*
+ * Record dependencies on roles mentioned in a new object's ACL.
+ */
+void
+recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId,
+ Oid ownerId, Acl *acl)
+{
+ int nmembers;
+ Oid *members;
+
+ /* Nothing to do if ACL is defaulted */
+ if (acl == NULL)
+ return;
+
+ /* Extract roles mentioned in ACL */
+ nmembers = aclmembers(acl, &members);
+
+ /* Update the shared dependency ACL info */
+ updateAclDependencies(classId, objectId, objsubId,
+ ownerId,
+ 0, NULL,
+ nmembers, members);
+}
+
+/*
+ * Record initial privileges for the top-level object passed in.
+ *
+ * For the object passed in, this will record its ACL (if any) and the ACLs of
+ * any sub-objects (eg: columns) into pg_init_privs.
+ *
+ * Any new kinds of objects which have ACLs associated with them and can be
+ * added to an extension should be added to the if-else tree below.
+ */
+void
+recordExtObjInitPriv(Oid objoid, Oid classoid)
+{
+ /*
+ * pg_class / pg_attribute
+ *
+ * If this is a relation then we need to see if there are any sub-objects
+ * (eg: columns) for it and, if so, be sure to call
+ * recordExtensionInitPrivWorker() for each one.
+ */
+ if (classoid == RelationRelationId)
+ {
+ Form_pg_class pg_class_tuple;
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", objoid);
+ pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
+
+ /*
+ * Indexes don't have permissions, neither do the pg_class rows for
+ * composite types. (These cases are unreachable given the
+ * restrictions in ALTER EXTENSION ADD, but let's check anyway.)
+ */
+ if (pg_class_tuple->relkind == RELKIND_INDEX ||
+ pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
+ pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+ {
+ ReleaseSysCache(tuple);
+ return;
+ }
+
+ /*
+ * If this isn't a sequence then it's possibly going to have
+ * column-level ACLs associated with it.
+ */
+ if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
+ {
+ AttrNumber curr_att;
+ AttrNumber nattrs = pg_class_tuple->relnatts;
+
+ for (curr_att = 1; curr_att <= nattrs; curr_att++)
+ {
+ HeapTuple attTuple;
+ Datum attaclDatum;
+
+ attTuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(objoid),
+ Int16GetDatum(curr_att));
+
+ if (!HeapTupleIsValid(attTuple))
+ continue;
+
+ /* ignore dropped columns */
+ if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
+ {
+ ReleaseSysCache(attTuple);
+ continue;
+ }
+
+ attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
+ Anum_pg_attribute_attacl,
+ &isNull);
+
+ /* no need to do anything for a NULL ACL */
+ if (isNull)
+ {
+ ReleaseSysCache(attTuple);
+ continue;
+ }
+
+ recordExtensionInitPrivWorker(objoid, classoid, curr_att,
+ DatumGetAclP(attaclDatum));
+
+ ReleaseSysCache(attTuple);
+ }
+ }
+
+ aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_foreign_data_wrapper */
+ else if (classoid == ForeignDataWrapperRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID,
+ ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for foreign data wrapper %u",
+ objoid);
+
+ aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
+ Anum_pg_foreign_data_wrapper_fdwacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_foreign_server */
+ else if (classoid == ForeignServerRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for foreign data wrapper %u",
+ objoid);
+
+ aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
+ Anum_pg_foreign_server_srvacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_language */
+ else if (classoid == LanguageRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for language %u", objoid);
+
+ aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_largeobject_metadata */
+ else if (classoid == LargeObjectMetadataRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+ ScanKeyData entry[1];
+ SysScanDesc scan;
+ Relation relation;
+
+ /*
+ * Note: this is dead code, given that we don't allow large objects to
+ * be made extension members. But it seems worth carrying in case
+ * some future caller of this function has need for it.
+ */
+ relation = table_open(LargeObjectMetadataRelationId, RowExclusiveLock);
+
+ /* There's no syscache for pg_largeobject_metadata */
+ ScanKeyInit(&entry[0],
+ Anum_pg_largeobject_metadata_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objoid));
+
+ scan = systable_beginscan(relation,
+ LargeObjectMetadataOidIndexId, true,
+ NULL, 1, entry);
+
+ tuple = systable_getnext(scan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "could not find tuple for large object %u", objoid);
+
+ aclDatum = heap_getattr(tuple,
+ Anum_pg_largeobject_metadata_lomacl,
+ RelationGetDescr(relation), &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ systable_endscan(scan);
+ }
+ /* pg_namespace */
+ else if (classoid == NamespaceRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", objoid);
+
+ aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple,
+ Anum_pg_namespace_nspacl, &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_proc */
+ else if (classoid == ProcedureRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", objoid);
+
+ aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ /* pg_type */
+ else if (classoid == TypeRelationId)
+ {
+ Datum aclDatum;
+ bool isNull;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", objoid);
+
+ aclDatum = SysCacheGetAttr(TYPEOID, tuple, Anum_pg_type_typacl,
+ &isNull);
+
+ /* Add the record, if any, for the top-level object */
+ if (!isNull)
+ recordExtensionInitPrivWorker(objoid, classoid, 0,
+ DatumGetAclP(aclDatum));
+
+ ReleaseSysCache(tuple);
+ }
+ else if (classoid == AccessMethodRelationId ||
+ classoid == AggregateRelationId ||
+ classoid == CastRelationId ||
+ classoid == CollationRelationId ||
+ classoid == ConversionRelationId ||
+ classoid == EventTriggerRelationId ||
+ classoid == OperatorRelationId ||
+ classoid == OperatorClassRelationId ||
+ classoid == OperatorFamilyRelationId ||
+ classoid == NamespaceRelationId ||
+ classoid == TSConfigRelationId ||
+ classoid == TSDictionaryRelationId ||
+ classoid == TSParserRelationId ||
+ classoid == TSTemplateRelationId ||
+ classoid == TransformRelationId
+ )
+ {
+ /* no ACL for these object types, so do nothing. */
+ }
+
+ /*
+ * complain if we are given a class OID for a class that extensions don't
+ * support or that we don't recognize.
+ */
+ else
+ {
+ elog(ERROR, "unrecognized or unsupported class OID: %u", classoid);
+ }
+}
+
+/*
+ * For the object passed in, remove its ACL and the ACLs of any object subIds
+ * from pg_init_privs (via recordExtensionInitPrivWorker()).
+ */
+void
+removeExtObjInitPriv(Oid objoid, Oid classoid)
+{
+ /*
+ * If this is a relation then we need to see if there are any sub-objects
+ * (eg: columns) for it and, if so, be sure to call
+ * recordExtensionInitPrivWorker() for each one.
+ */
+ if (classoid == RelationRelationId)
+ {
+ Form_pg_class pg_class_tuple;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", objoid);
+ pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
+
+ /*
+ * Indexes don't have permissions, neither do the pg_class rows for
+ * composite types. (These cases are unreachable given the
+ * restrictions in ALTER EXTENSION DROP, but let's check anyway.)
+ */
+ if (pg_class_tuple->relkind == RELKIND_INDEX ||
+ pg_class_tuple->relkind == RELKIND_PARTITIONED_INDEX ||
+ pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+ {
+ ReleaseSysCache(tuple);
+ return;
+ }
+
+ /*
+ * If this isn't a sequence then it's possibly going to have
+ * column-level ACLs associated with it.
+ */
+ if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
+ {
+ AttrNumber curr_att;
+ AttrNumber nattrs = pg_class_tuple->relnatts;
+
+ for (curr_att = 1; curr_att <= nattrs; curr_att++)
+ {
+ HeapTuple attTuple;
+
+ attTuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(objoid),
+ Int16GetDatum(curr_att));
+
+ if (!HeapTupleIsValid(attTuple))
+ continue;
+
+ /* when removing, remove all entries, even dropped columns */
+
+ recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
+
+ ReleaseSysCache(attTuple);
+ }
+ }
+
+ ReleaseSysCache(tuple);
+ }
+
+ /* Remove the record, if any, for the top-level object */
+ recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
+}
+
+/*
+ * Record initial ACL for an extension object
+ *
+ * Can be called at any time, we check if 'creating_extension' is set and, if
+ * not, exit immediately.
+ *
+ * Pass in the object OID, the OID of the class (the OID of the table which
+ * the object is defined in) and the 'sub' id of the object (objsubid), if
+ * any. If there is no 'sub' id (they are currently only used for columns of
+ * tables) then pass in '0'. Finally, pass in the complete ACL to store.
+ *
+ * If an ACL already exists for this object/sub-object then we will replace
+ * it with what is passed in.
+ *
+ * Passing in NULL for 'new_acl' will result in the entry for the object being
+ * removed, if one is found.
+ */
+static void
+recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
+{
+ /*
+ * Generally, we only record the initial privileges when an extension is
+ * being created, but because we don't actually use CREATE EXTENSION
+ * during binary upgrades with pg_upgrade, there is a variable to let us
+ * know that the GRANT and REVOKE statements being issued, while this
+ * variable is true, are for the initial privileges of the extension
+ * object and therefore we need to record them.
+ */
+ if (!creating_extension && !binary_upgrade_record_init_privs)
+ return;
+
+ recordExtensionInitPrivWorker(objoid, classoid, objsubid, new_acl);
+}
+
+/*
+ * Record initial ACL for an extension object, worker.
+ *
+ * This will perform a wholesale replacement of the entire ACL for the object
+ * passed in, therefore be sure to pass in the complete new ACL to use.
+ *
+ * Generally speaking, do *not* use this function directly but instead use
+ * recordExtensionInitPriv(), which checks if 'creating_extension' is set.
+ * This function does *not* check if 'creating_extension' is set as it is also
+ * used when an object is added to or removed from an extension via ALTER
+ * EXTENSION ... ADD/DROP.
+ */
+static void
+recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
+{
+ Relation relation;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ HeapTuple oldtuple;
+
+ relation = table_open(InitPrivsRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_init_privs_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objoid));
+ ScanKeyInit(&key[1],
+ Anum_pg_init_privs_classoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classoid));
+ ScanKeyInit(&key[2],
+ Anum_pg_init_privs_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(objsubid));
+
+ scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
+ NULL, 3, key);
+
+ /* There should exist only one entry or none. */
+ oldtuple = systable_getnext(scan);
+
+ /* If we find an entry, update it with the latest ACL. */
+ if (HeapTupleIsValid(oldtuple))
+ {
+ Datum values[Natts_pg_init_privs];
+ bool nulls[Natts_pg_init_privs];
+ bool replace[Natts_pg_init_privs];
+
+ /* If we have a new ACL to set, then update the row with it. */
+ if (new_acl)
+ {
+ MemSet(values, 0, sizeof(values));
+ MemSet(nulls, false, sizeof(nulls));
+ MemSet(replace, false, sizeof(replace));
+
+ values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
+ replace[Anum_pg_init_privs_initprivs - 1] = true;
+
+ oldtuple = heap_modify_tuple(oldtuple, RelationGetDescr(relation),
+ values, nulls, replace);
+
+ CatalogTupleUpdate(relation, &oldtuple->t_self, oldtuple);
+ }
+ else
+ {
+ /* new_acl is NULL, so delete the entry we found. */
+ CatalogTupleDelete(relation, &oldtuple->t_self);
+ }
+ }
+ else
+ {
+ Datum values[Natts_pg_init_privs];
+ bool nulls[Natts_pg_init_privs];
+
+ /*
+ * Only add a new entry if the new ACL is non-NULL.
+ *
+ * If we are passed in a NULL ACL and no entry exists, we can just
+ * fall through and do nothing.
+ */
+ if (new_acl)
+ {
+ /* No entry found, so add it. */
+ MemSet(nulls, false, sizeof(nulls));
+
+ values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
+ values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
+ values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
+
+ /* This function only handles initial privileges of extensions */
+ values[Anum_pg_init_privs_privtype - 1] =
+ CharGetDatum(INITPRIVS_EXTENSION);
+
+ values[Anum_pg_init_privs_initprivs - 1] = PointerGetDatum(new_acl);
+
+ tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
+
+ CatalogTupleInsert(relation, tuple);
+ }
+ }
+
+ systable_endscan(scan);
+
+ /* prevent error when processing objects multiple times */
+ CommandCounterIncrement();
+
+ table_close(relation, RowExclusiveLock);
+}
diff --git a/src/backend/catalog/bki-stamp b/src/backend/catalog/bki-stamp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/backend/catalog/bki-stamp
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
new file mode 100644
index 0000000..7d6acae
--- /dev/null
+++ b/src/backend/catalog/catalog.c
@@ -0,0 +1,533 @@
+/*-------------------------------------------------------------------------
+ *
+ * catalog.c
+ * routines concerned with catalog naming conventions and other
+ * bits of hard-wired knowledge
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/catalog.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/table.h"
+#include "access/transam.h"
+#include "catalog/catalog.h"
+#include "catalog/indexing.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_auth_members.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_database.h"
+#include "catalog/pg_db_role_setting.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_replication_origin.h"
+#include "catalog/pg_shdepend.h"
+#include "catalog/pg_shdescription.h"
+#include "catalog/pg_shseclabel.h"
+#include "catalog/pg_subscription.h"
+#include "catalog/pg_tablespace.h"
+#include "catalog/pg_type.h"
+#include "catalog/toasting.h"
+#include "miscadmin.h"
+#include "storage/fd.h"
+#include "utils/fmgroids.h"
+#include "utils/fmgrprotos.h"
+#include "utils/rel.h"
+#include "utils/snapmgr.h"
+#include "utils/syscache.h"
+
+/*
+ * IsSystemRelation
+ * True iff the relation is either a system catalog or a toast table.
+ * See IsCatalogRelation for the exact definition of a system catalog.
+ *
+ * We treat toast tables of user relations as "system relations" for
+ * protection purposes, e.g. you can't change their schemas without
+ * special permissions. Therefore, most uses of this function are
+ * checking whether allow_system_table_mods restrictions apply.
+ * For other purposes, consider whether you shouldn't be using
+ * IsCatalogRelation instead.
+ *
+ * This function does not perform any catalog accesses.
+ * Some callers rely on that!
+ */
+bool
+IsSystemRelation(Relation relation)
+{
+ return IsSystemClass(RelationGetRelid(relation), relation->rd_rel);
+}
+
+/*
+ * IsSystemClass
+ * Like the above, but takes a Form_pg_class as argument.
+ * Used when we do not want to open the relation and have to
+ * search pg_class directly.
+ */
+bool
+IsSystemClass(Oid relid, Form_pg_class reltuple)
+{
+ /* IsCatalogRelationOid is a bit faster, so test that first */
+ return (IsCatalogRelationOid(relid) || IsToastClass(reltuple));
+}
+
+/*
+ * IsCatalogRelation
+ * True iff the relation is a system catalog.
+ *
+ * By a system catalog, we mean one that is created during the bootstrap
+ * phase of initdb. That includes not just the catalogs per se, but
+ * also their indexes, and TOAST tables and indexes if any.
+ *
+ * This function does not perform any catalog accesses.
+ * Some callers rely on that!
+ */
+bool
+IsCatalogRelation(Relation relation)
+{
+ return IsCatalogRelationOid(RelationGetRelid(relation));
+}
+
+/*
+ * IsCatalogRelationOid
+ * True iff the relation identified by this OID is a system catalog.
+ *
+ * By a system catalog, we mean one that is created during the bootstrap
+ * phase of initdb. That includes not just the catalogs per se, but
+ * also their indexes, and TOAST tables and indexes if any.
+ *
+ * This function does not perform any catalog accesses.
+ * Some callers rely on that!
+ */
+bool
+IsCatalogRelationOid(Oid relid)
+{
+ /*
+ * We consider a relation to be a system catalog if it has an OID that was
+ * manually assigned or assigned by genbki.pl. This includes all the
+ * defined catalogs, their indexes, and their TOAST tables and indexes.
+ *
+ * This rule excludes the relations in information_schema, which are not
+ * integral to the system and can be treated the same as user relations.
+ * (Since it's valid to drop and recreate information_schema, any rule
+ * that did not act this way would be wrong.)
+ *
+ * This test is reliable since an OID wraparound will skip this range of
+ * OIDs; see GetNewObjectId().
+ */
+ return (relid < (Oid) FirstBootstrapObjectId);
+}
+
+/*
+ * IsToastRelation
+ * True iff relation is a TOAST support relation (or index).
+ *
+ * Does not perform any catalog accesses.
+ */
+bool
+IsToastRelation(Relation relation)
+{
+ /*
+ * What we actually check is whether the relation belongs to a pg_toast
+ * namespace. This should be equivalent because of restrictions that are
+ * enforced elsewhere against creating user relations in, or moving
+ * relations into/out of, a pg_toast namespace. Notice also that this
+ * will not say "true" for toast tables belonging to other sessions' temp
+ * tables; we expect that other mechanisms will prevent access to those.
+ */
+ return IsToastNamespace(RelationGetNamespace(relation));
+}
+
+/*
+ * IsToastClass
+ * Like the above, but takes a Form_pg_class as argument.
+ * Used when we do not want to open the relation and have to
+ * search pg_class directly.
+ */
+bool
+IsToastClass(Form_pg_class reltuple)
+{
+ Oid relnamespace = reltuple->relnamespace;
+
+ return IsToastNamespace(relnamespace);
+}
+
+/*
+ * IsCatalogNamespace
+ * True iff namespace is pg_catalog.
+ *
+ * Does not perform any catalog accesses.
+ *
+ * NOTE: the reason this isn't a macro is to avoid having to include
+ * catalog/pg_namespace.h in a lot of places.
+ */
+bool
+IsCatalogNamespace(Oid namespaceId)
+{
+ return namespaceId == PG_CATALOG_NAMESPACE;
+}
+
+/*
+ * IsToastNamespace
+ * True iff namespace is pg_toast or my temporary-toast-table namespace.
+ *
+ * Does not perform any catalog accesses.
+ *
+ * Note: this will return false for temporary-toast-table namespaces belonging
+ * to other backends. Those are treated the same as other backends' regular
+ * temp table namespaces, and access is prevented where appropriate.
+ * If you need to check for those, you may be able to use isAnyTempNamespace,
+ * but beware that that does involve a catalog access.
+ */
+bool
+IsToastNamespace(Oid namespaceId)
+{
+ return (namespaceId == PG_TOAST_NAMESPACE) ||
+ isTempToastNamespace(namespaceId);
+}
+
+
+/*
+ * IsReservedName
+ * True iff name starts with the pg_ prefix.
+ *
+ * For some classes of objects, the prefix pg_ is reserved for
+ * system objects only. As of 8.0, this was only true for
+ * schema and tablespace names. With 9.6, this is also true
+ * for roles.
+ */
+bool
+IsReservedName(const char *name)
+{
+ /* ugly coding for speed */
+ return (name[0] == 'p' &&
+ name[1] == 'g' &&
+ name[2] == '_');
+}
+
+
+/*
+ * IsSharedRelation
+ * Given the OID of a relation, determine whether it's supposed to be
+ * shared across an entire database cluster.
+ *
+ * In older releases, this had to be hard-wired so that we could compute the
+ * locktag for a relation and lock it before examining its catalog entry.
+ * Since we now have MVCC catalog access, the race conditions that made that
+ * a hard requirement are gone, so we could look at relaxing this restriction.
+ * However, if we scanned the pg_class entry to find relisshared, and only
+ * then locked the relation, pg_class could get updated in the meantime,
+ * forcing us to scan the relation again, which would definitely be complex
+ * and might have undesirable performance consequences. Fortunately, the set
+ * of shared relations is fairly static, so a hand-maintained list of their
+ * OIDs isn't completely impractical.
+ */
+bool
+IsSharedRelation(Oid relationId)
+{
+ /* These are the shared catalogs (look for BKI_SHARED_RELATION) */
+ if (relationId == AuthIdRelationId ||
+ relationId == AuthMemRelationId ||
+ relationId == DatabaseRelationId ||
+ relationId == SharedDescriptionRelationId ||
+ relationId == SharedDependRelationId ||
+ relationId == SharedSecLabelRelationId ||
+ relationId == TableSpaceRelationId ||
+ relationId == DbRoleSettingRelationId ||
+ relationId == ReplicationOriginRelationId ||
+ relationId == SubscriptionRelationId)
+ return true;
+ /* These are their indexes (see indexing.h) */
+ if (relationId == AuthIdRolnameIndexId ||
+ relationId == AuthIdOidIndexId ||
+ relationId == AuthMemRoleMemIndexId ||
+ relationId == AuthMemMemRoleIndexId ||
+ relationId == DatabaseNameIndexId ||
+ relationId == DatabaseOidIndexId ||
+ relationId == SharedDescriptionObjIndexId ||
+ relationId == SharedDependDependerIndexId ||
+ relationId == SharedDependReferenceIndexId ||
+ relationId == SharedSecLabelObjectIndexId ||
+ relationId == TablespaceOidIndexId ||
+ relationId == TablespaceNameIndexId ||
+ relationId == DbRoleSettingDatidRolidIndexId ||
+ relationId == ReplicationOriginIdentIndex ||
+ relationId == ReplicationOriginNameIndex ||
+ relationId == SubscriptionObjectIndexId ||
+ relationId == SubscriptionNameIndexId)
+ return true;
+ /* These are their toast tables and toast indexes (see toasting.h) */
+ if (relationId == PgAuthidToastTable ||
+ relationId == PgAuthidToastIndex ||
+ relationId == PgDatabaseToastTable ||
+ relationId == PgDatabaseToastIndex ||
+ relationId == PgDbRoleSettingToastTable ||
+ relationId == PgDbRoleSettingToastIndex ||
+ relationId == PgReplicationOriginToastTable ||
+ relationId == PgReplicationOriginToastIndex ||
+ relationId == PgShdescriptionToastTable ||
+ relationId == PgShdescriptionToastIndex ||
+ relationId == PgShseclabelToastTable ||
+ relationId == PgShseclabelToastIndex ||
+ relationId == PgSubscriptionToastTable ||
+ relationId == PgSubscriptionToastIndex ||
+ relationId == PgTablespaceToastTable ||
+ relationId == PgTablespaceToastIndex)
+ return true;
+ return false;
+}
+
+
+/*
+ * GetNewOidWithIndex
+ * Generate a new OID that is unique within the system relation.
+ *
+ * Since the OID is not immediately inserted into the table, there is a
+ * race condition here; but a problem could occur only if someone else
+ * managed to cycle through 2^32 OIDs and generate the same OID before we
+ * finish inserting our row. This seems unlikely to be a problem. Note
+ * that if we had to *commit* the row to end the race condition, the risk
+ * would be rather higher; therefore we use SnapshotAny in the test, so that
+ * we will see uncommitted rows. (We used to use SnapshotDirty, but that has
+ * the disadvantage that it ignores recently-deleted rows, creating a risk
+ * of transient conflicts for as long as our own MVCC snapshots think a
+ * recently-deleted row is live. The risk is far higher when selecting TOAST
+ * OIDs, because SnapshotToast considers dead rows as active indefinitely.)
+ *
+ * Note that we are effectively assuming that the table has a relatively small
+ * number of entries (much less than 2^32) and there aren't very long runs of
+ * consecutive existing OIDs. This is a mostly reasonable assumption for
+ * system catalogs.
+ *
+ * Caller must have a suitable lock on the relation.
+ */
+Oid
+GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
+{
+ Oid newOid;
+ SysScanDesc scan;
+ ScanKeyData key;
+ bool collides;
+
+ /* Only system relations are supported */
+ Assert(IsSystemRelation(relation));
+
+ /* In bootstrap mode, we don't have any indexes to use */
+ if (IsBootstrapProcessingMode())
+ return GetNewObjectId();
+
+ /*
+ * We should never be asked to generate a new pg_type OID during
+ * pg_upgrade; doing so would risk collisions with the OIDs it wants to
+ * assign. Hitting this assert means there's some path where we failed to
+ * ensure that a type OID is determined by commands in the dump script.
+ */
+ Assert(!IsBinaryUpgrade || RelationGetRelid(relation) != TypeRelationId);
+
+ /* Generate new OIDs until we find one not in the table */
+ do
+ {
+ CHECK_FOR_INTERRUPTS();
+
+ newOid = GetNewObjectId();
+
+ ScanKeyInit(&key,
+ oidcolumn,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(newOid));
+
+ /* see notes above about using SnapshotAny */
+ scan = systable_beginscan(relation, indexId, true,
+ SnapshotAny, 1, &key);
+
+ collides = HeapTupleIsValid(systable_getnext(scan));
+
+ systable_endscan(scan);
+ } while (collides);
+
+ return newOid;
+}
+
+/*
+ * GetNewRelFileNode
+ * Generate a new relfilenode number that is unique within the
+ * database of the given tablespace.
+ *
+ * If the relfilenode will also be used as the relation's OID, pass the
+ * opened pg_class catalog, and this routine will guarantee that the result
+ * is also an unused OID within pg_class. If the result is to be used only
+ * as a relfilenode for an existing relation, pass NULL for pg_class.
+ *
+ * As with GetNewOidWithIndex(), there is some theoretical risk of a race
+ * condition, but it doesn't seem worth worrying about.
+ *
+ * Note: we don't support using this in bootstrap mode. All relations
+ * created by bootstrap have preassigned OIDs, so there's no need.
+ */
+Oid
+GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
+{
+ RelFileNodeBackend rnode;
+ char *rpath;
+ bool collides;
+ BackendId backend;
+
+ /*
+ * If we ever get here during pg_upgrade, there's something wrong; all
+ * relfilenode assignments during a binary-upgrade run should be
+ * determined by commands in the dump script.
+ */
+ Assert(!IsBinaryUpgrade);
+
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_TEMP:
+ backend = BackendIdForTempRelations();
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ case RELPERSISTENCE_PERMANENT:
+ backend = InvalidBackendId;
+ break;
+ default:
+ elog(ERROR, "invalid relpersistence: %c", relpersistence);
+ return InvalidOid; /* placate compiler */
+ }
+
+ /* This logic should match RelationInitPhysicalAddr */
+ rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
+ rnode.node.dbNode = (rnode.node.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : MyDatabaseId;
+
+ /*
+ * The relpath will vary based on the backend ID, so we must initialize
+ * that properly here to make sure that any collisions based on filename
+ * are properly detected.
+ */
+ rnode.backend = backend;
+
+ do
+ {
+ CHECK_FOR_INTERRUPTS();
+
+ /* Generate the OID */
+ if (pg_class)
+ rnode.node.relNode = GetNewOidWithIndex(pg_class, ClassOidIndexId,
+ Anum_pg_class_oid);
+ else
+ rnode.node.relNode = GetNewObjectId();
+
+ /* Check for existing file of same name */
+ rpath = relpath(rnode, MAIN_FORKNUM);
+
+ if (access(rpath, F_OK) == 0)
+ {
+ /* definite collision */
+ collides = true;
+ }
+ else
+ {
+ /*
+ * Here we have a little bit of a dilemma: if errno is something
+ * other than ENOENT, should we declare a collision and loop? In
+ * practice it seems best to go ahead regardless of the errno. If
+ * there is a colliding file we will get an smgr failure when we
+ * attempt to create the new relation file.
+ */
+ collides = false;
+ }
+
+ pfree(rpath);
+ } while (collides);
+
+ return rnode.node.relNode;
+}
+
+/*
+ * SQL callable interface for GetNewOidWithIndex(). Outside of initdb's
+ * direct insertions into catalog tables, and recovering from corruption, this
+ * should rarely be needed.
+ *
+ * Function is intentionally not documented in the user facing docs.
+ */
+Datum
+pg_nextoid(PG_FUNCTION_ARGS)
+{
+ Oid reloid = PG_GETARG_OID(0);
+ Name attname = PG_GETARG_NAME(1);
+ Oid idxoid = PG_GETARG_OID(2);
+ Relation rel;
+ Relation idx;
+ HeapTuple atttuple;
+ Form_pg_attribute attform;
+ AttrNumber attno;
+ Oid newoid;
+
+ /*
+ * As this function is not intended to be used during normal running, and
+ * only supports system catalogs (which require superuser permissions to
+ * modify), just checking for superuser ought to not obstruct valid
+ * usecases.
+ */
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser to call pg_nextoid()")));
+
+ rel = table_open(reloid, RowExclusiveLock);
+ idx = index_open(idxoid, RowExclusiveLock);
+
+ if (!IsSystemRelation(rel))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("pg_nextoid() can only be used on system catalogs")));
+
+ if (idx->rd_index->indrelid != RelationGetRelid(rel))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("index \"%s\" does not belong to table \"%s\"",
+ RelationGetRelationName(idx),
+ RelationGetRelationName(rel))));
+
+ atttuple = SearchSysCacheAttName(reloid, NameStr(*attname));
+ if (!HeapTupleIsValid(atttuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ NameStr(*attname), RelationGetRelationName(rel))));
+
+ attform = ((Form_pg_attribute) GETSTRUCT(atttuple));
+ attno = attform->attnum;
+
+ if (attform->atttypid != OIDOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("column \"%s\" is not of type oid",
+ NameStr(*attname))));
+
+ if (IndexRelationGetNumberOfKeyAttributes(idx) != 1 ||
+ idx->rd_index->indkey.values[0] != attno)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("index \"%s\" is not the index for column \"%s\"",
+ RelationGetRelationName(idx),
+ NameStr(*attname))));
+
+ newoid = GetNewOidWithIndex(rel, idxoid, attno);
+
+ ReleaseSysCache(atttuple);
+ table_close(rel, RowExclusiveLock);
+ index_close(idx, RowExclusiveLock);
+
+ return newoid;
+}
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
new file mode 100644
index 0000000..5565e6f
--- /dev/null
+++ b/src/backend/catalog/dependency.c
@@ -0,0 +1,2894 @@
+/*-------------------------------------------------------------------------
+ *
+ * dependency.c
+ * Routines to support inter-object dependencies.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/dependency.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "access/xact.h"
+#include "catalog/dependency.h"
+#include "catalog/heap.h"
+#include "catalog/index.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_amop.h"
+#include "catalog/pg_amproc.h"
+#include "catalog/pg_attrdef.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_cast.h"
+#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_depend.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_init_privs.h"
+#include "catalog/pg_language.h"
+#include "catalog/pg_largeobject.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_opfamily.h"
+#include "catalog/pg_policy.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_publication.h"
+#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"
+#include "catalog/pg_ts_dict.h"
+#include "catalog/pg_ts_parser.h"
+#include "catalog/pg_ts_template.h"
+#include "catalog/pg_type.h"
+#include "catalog/pg_user_mapping.h"
+#include "commands/comment.h"
+#include "commands/defrem.h"
+#include "commands/event_trigger.h"
+#include "commands/extension.h"
+#include "commands/policy.h"
+#include "commands/proclang.h"
+#include "commands/publicationcmds.h"
+#include "commands/schemacmds.h"
+#include "commands/seclabel.h"
+#include "commands/sequence.h"
+#include "commands/trigger.h"
+#include "commands/typecmds.h"
+#include "nodes/nodeFuncs.h"
+#include "parser/parsetree.h"
+#include "rewrite/rewriteRemove.h"
+#include "storage/lmgr.h"
+#include "utils/acl.h"
+#include "utils/fmgroids.h"
+#include "utils/guc.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
+
+
+/*
+ * Deletion processing requires additional state for each ObjectAddress that
+ * it's planning to delete. For simplicity and code-sharing we make the
+ * ObjectAddresses code support arrays with or without this extra state.
+ */
+typedef struct
+{
+ int flags; /* bitmask, see bit definitions below */
+ ObjectAddress dependee; /* object whose deletion forced this one */
+} ObjectAddressExtra;
+
+/* ObjectAddressExtra flag bits */
+#define DEPFLAG_ORIGINAL 0x0001 /* an original deletion target */
+#define DEPFLAG_NORMAL 0x0002 /* reached via normal dependency */
+#define DEPFLAG_AUTO 0x0004 /* reached via auto dependency */
+#define DEPFLAG_INTERNAL 0x0008 /* reached via internal dependency */
+#define DEPFLAG_PARTITION 0x0010 /* reached via partition dependency */
+#define DEPFLAG_EXTENSION 0x0020 /* reached via extension dependency */
+#define DEPFLAG_REVERSE 0x0040 /* reverse internal/extension link */
+#define DEPFLAG_IS_PART 0x0080 /* has a partition dependency */
+#define DEPFLAG_SUBOBJECT 0x0100 /* subobject of another deletable object */
+
+
+/* expansible list of ObjectAddresses */
+struct ObjectAddresses
+{
+ ObjectAddress *refs; /* => palloc'd array */
+ ObjectAddressExtra *extras; /* => palloc'd array, or NULL if not used */
+ int numrefs; /* current number of references */
+ int maxrefs; /* current size of palloc'd array(s) */
+};
+
+/* typedef ObjectAddresses appears in dependency.h */
+
+/* threaded list of ObjectAddresses, for recursion detection */
+typedef struct ObjectAddressStack
+{
+ const ObjectAddress *object; /* object being visited */
+ int flags; /* its current flag bits */
+ struct ObjectAddressStack *next; /* next outer stack level */
+} ObjectAddressStack;
+
+/* temporary storage in findDependentObjects */
+typedef struct
+{
+ ObjectAddress obj; /* object to be deleted --- MUST BE FIRST */
+ int subflags; /* flags to pass down when recursing to obj */
+} ObjectAddressAndFlags;
+
+/* for find_expr_references_walker */
+typedef struct
+{
+ ObjectAddresses *addrs; /* addresses being accumulated */
+ List *rtables; /* list of rangetables to resolve Vars */
+} find_expr_references_context;
+
+/*
+ * This constant table maps ObjectClasses to the corresponding catalog OIDs.
+ * See also getObjectClass().
+ */
+static const Oid object_classes[] = {
+ RelationRelationId, /* OCLASS_CLASS */
+ ProcedureRelationId, /* OCLASS_PROC */
+ TypeRelationId, /* OCLASS_TYPE */
+ CastRelationId, /* OCLASS_CAST */
+ CollationRelationId, /* OCLASS_COLLATION */
+ ConstraintRelationId, /* OCLASS_CONSTRAINT */
+ ConversionRelationId, /* OCLASS_CONVERSION */
+ AttrDefaultRelationId, /* OCLASS_DEFAULT */
+ LanguageRelationId, /* OCLASS_LANGUAGE */
+ LargeObjectRelationId, /* OCLASS_LARGEOBJECT */
+ OperatorRelationId, /* OCLASS_OPERATOR */
+ OperatorClassRelationId, /* OCLASS_OPCLASS */
+ OperatorFamilyRelationId, /* OCLASS_OPFAMILY */
+ AccessMethodRelationId, /* OCLASS_AM */
+ AccessMethodOperatorRelationId, /* OCLASS_AMOP */
+ AccessMethodProcedureRelationId, /* OCLASS_AMPROC */
+ RewriteRelationId, /* OCLASS_REWRITE */
+ TriggerRelationId, /* OCLASS_TRIGGER */
+ NamespaceRelationId, /* OCLASS_SCHEMA */
+ StatisticExtRelationId, /* OCLASS_STATISTIC_EXT */
+ TSParserRelationId, /* OCLASS_TSPARSER */
+ TSDictionaryRelationId, /* OCLASS_TSDICT */
+ TSTemplateRelationId, /* OCLASS_TSTEMPLATE */
+ TSConfigRelationId, /* OCLASS_TSCONFIG */
+ AuthIdRelationId, /* OCLASS_ROLE */
+ DatabaseRelationId, /* OCLASS_DATABASE */
+ TableSpaceRelationId, /* OCLASS_TBLSPACE */
+ ForeignDataWrapperRelationId, /* OCLASS_FDW */
+ ForeignServerRelationId, /* OCLASS_FOREIGN_SERVER */
+ UserMappingRelationId, /* OCLASS_USER_MAPPING */
+ DefaultAclRelationId, /* OCLASS_DEFACL */
+ ExtensionRelationId, /* OCLASS_EXTENSION */
+ EventTriggerRelationId, /* OCLASS_EVENT_TRIGGER */
+ PolicyRelationId, /* OCLASS_POLICY */
+ PublicationRelationId, /* OCLASS_PUBLICATION */
+ PublicationRelRelationId, /* OCLASS_PUBLICATION_REL */
+ SubscriptionRelationId, /* OCLASS_SUBSCRIPTION */
+ TransformRelationId /* OCLASS_TRANSFORM */
+};
+
+
+static void findDependentObjects(const ObjectAddress *object,
+ int objflags,
+ int flags,
+ ObjectAddressStack *stack,
+ ObjectAddresses *targetObjects,
+ const ObjectAddresses *pendingObjects,
+ Relation *depRel);
+static void reportDependentObjects(const ObjectAddresses *targetObjects,
+ DropBehavior behavior,
+ int flags,
+ const ObjectAddress *origObject);
+static void deleteOneObject(const ObjectAddress *object,
+ Relation *depRel, int32 flags);
+static void doDeletion(const ObjectAddress *object, int flags);
+static bool find_expr_references_walker(Node *node,
+ find_expr_references_context *context);
+static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
+static int object_address_comparator(const void *a, const void *b);
+static void add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
+ ObjectAddresses *addrs);
+static void add_exact_object_address_extra(const ObjectAddress *object,
+ const ObjectAddressExtra *extra,
+ ObjectAddresses *addrs);
+static bool object_address_present_add_flags(const ObjectAddress *object,
+ int flags,
+ ObjectAddresses *addrs);
+static bool stack_address_present_add_flags(const ObjectAddress *object,
+ int flags,
+ ObjectAddressStack *stack);
+static void DeleteInitPrivs(const ObjectAddress *object);
+
+
+/*
+ * Go through the objects given running the final actions on them, and execute
+ * the actual deletion.
+ */
+static void
+deleteObjectsInList(ObjectAddresses *targetObjects, Relation *depRel,
+ int flags)
+{
+ int i;
+
+ /*
+ * Keep track of objects for event triggers, if necessary.
+ */
+ if (trackDroppedObjectsNeeded() && !(flags & PERFORM_DELETION_INTERNAL))
+ {
+ for (i = 0; i < targetObjects->numrefs; i++)
+ {
+ const ObjectAddress *thisobj = &targetObjects->refs[i];
+ const ObjectAddressExtra *extra = &targetObjects->extras[i];
+ bool original = false;
+ bool normal = false;
+
+ if (extra->flags & DEPFLAG_ORIGINAL)
+ original = true;
+ if (extra->flags & DEPFLAG_NORMAL)
+ normal = true;
+ if (extra->flags & DEPFLAG_REVERSE)
+ normal = true;
+
+ if (EventTriggerSupportsObjectClass(getObjectClass(thisobj)))
+ {
+ EventTriggerSQLDropAddObject(thisobj, original, normal);
+ }
+ }
+ }
+
+ /*
+ * Delete all the objects in the proper order, except that if told to, we
+ * should skip the original object(s).
+ */
+ for (i = 0; i < targetObjects->numrefs; i++)
+ {
+ ObjectAddress *thisobj = targetObjects->refs + i;
+ ObjectAddressExtra *thisextra = targetObjects->extras + i;
+
+ if ((flags & PERFORM_DELETION_SKIP_ORIGINAL) &&
+ (thisextra->flags & DEPFLAG_ORIGINAL))
+ continue;
+
+ deleteOneObject(thisobj, depRel, flags);
+ }
+}
+
+/*
+ * performDeletion: attempt to drop the specified object. If CASCADE
+ * behavior is specified, also drop any dependent objects (recursively).
+ * If RESTRICT behavior is specified, error out if there are any dependent
+ * objects, except for those that should be implicitly dropped anyway
+ * according to the dependency type.
+ *
+ * This is the outer control routine for all forms of DROP that drop objects
+ * that can participate in dependencies. Note that performMultipleDeletions
+ * is a variant on the same theme; if you change anything here you'll likely
+ * need to fix that too.
+ *
+ * Bits in the flags argument can include:
+ *
+ * PERFORM_DELETION_INTERNAL: indicates that the drop operation is not the
+ * direct result of a user-initiated action. For example, when a temporary
+ * schema is cleaned out so that a new backend can use it, or when a column
+ * default is dropped as an intermediate step while adding a new one, that's
+ * an internal operation. On the other hand, when we drop something because
+ * the user issued a DROP statement against it, that's not internal. Currently
+ * this suppresses calling event triggers and making some permissions checks.
+ *
+ * PERFORM_DELETION_CONCURRENTLY: perform the drop concurrently. This does
+ * not currently work for anything except dropping indexes; don't set it for
+ * other object types or you may get strange results.
+ *
+ * PERFORM_DELETION_QUIETLY: reduce message level from NOTICE to DEBUG2.
+ *
+ * PERFORM_DELETION_SKIP_ORIGINAL: do not delete the specified object(s),
+ * but only what depends on it/them.
+ *
+ * PERFORM_DELETION_SKIP_EXTENSIONS: do not delete extensions, even when
+ * deleting objects that are part of an extension. This should generally
+ * be used only when dropping temporary objects.
+ *
+ * PERFORM_DELETION_CONCURRENT_LOCK: perform the drop normally but with a lock
+ * as if it were concurrent. This is used by REINDEX CONCURRENTLY.
+ *
+ */
+void
+performDeletion(const ObjectAddress *object,
+ DropBehavior behavior, int flags)
+{
+ Relation depRel;
+ ObjectAddresses *targetObjects;
+
+ /*
+ * We save some cycles by opening pg_depend just once and passing the
+ * Relation pointer down to all the recursive deletion steps.
+ */
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ /*
+ * Acquire deletion lock on the target object. (Ideally the caller has
+ * done this already, but many places are sloppy about it.)
+ */
+ AcquireDeletionLock(object, 0);
+
+ /*
+ * Construct a list of objects to delete (ie, the given object plus
+ * everything directly or indirectly dependent on it).
+ */
+ targetObjects = new_object_addresses();
+
+ findDependentObjects(object,
+ DEPFLAG_ORIGINAL,
+ flags,
+ NULL, /* empty stack */
+ targetObjects,
+ NULL, /* no pendingObjects */
+ &depRel);
+
+ /*
+ * Check if deletion is allowed, and report about cascaded deletes.
+ */
+ reportDependentObjects(targetObjects,
+ behavior,
+ flags,
+ object);
+
+ /* do the deed */
+ deleteObjectsInList(targetObjects, &depRel, flags);
+
+ /* And clean up */
+ free_object_addresses(targetObjects);
+
+ table_close(depRel, RowExclusiveLock);
+}
+
+/*
+ * performMultipleDeletions: Similar to performDeletion, but act on multiple
+ * objects at once.
+ *
+ * The main difference from issuing multiple performDeletion calls is that the
+ * list of objects that would be implicitly dropped, for each object to be
+ * dropped, is the union of the implicit-object list for all objects. This
+ * makes each check be more relaxed.
+ */
+void
+performMultipleDeletions(const ObjectAddresses *objects,
+ DropBehavior behavior, int flags)
+{
+ Relation depRel;
+ ObjectAddresses *targetObjects;
+ int i;
+
+ /* No work if no objects... */
+ if (objects->numrefs <= 0)
+ return;
+
+ /*
+ * We save some cycles by opening pg_depend just once and passing the
+ * Relation pointer down to all the recursive deletion steps.
+ */
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ /*
+ * Construct a list of objects to delete (ie, the given objects plus
+ * everything directly or indirectly dependent on them). Note that
+ * because we pass the whole objects list as pendingObjects context, we
+ * won't get a failure from trying to delete an object that is internally
+ * dependent on another one in the list; we'll just skip that object and
+ * delete it when we reach its owner.
+ */
+ targetObjects = new_object_addresses();
+
+ for (i = 0; i < objects->numrefs; i++)
+ {
+ const ObjectAddress *thisobj = objects->refs + i;
+
+ /*
+ * Acquire deletion lock on each target object. (Ideally the caller
+ * has done this already, but many places are sloppy about it.)
+ */
+ AcquireDeletionLock(thisobj, flags);
+
+ findDependentObjects(thisobj,
+ DEPFLAG_ORIGINAL,
+ flags,
+ NULL, /* empty stack */
+ targetObjects,
+ objects,
+ &depRel);
+ }
+
+ /*
+ * Check if deletion is allowed, and report about cascaded deletes.
+ *
+ * If there's exactly one object being deleted, report it the same way as
+ * in performDeletion(), else we have to be vaguer.
+ */
+ reportDependentObjects(targetObjects,
+ behavior,
+ flags,
+ (objects->numrefs == 1 ? objects->refs : NULL));
+
+ /* do the deed */
+ deleteObjectsInList(targetObjects, &depRel, flags);
+
+ /* And clean up */
+ free_object_addresses(targetObjects);
+
+ table_close(depRel, RowExclusiveLock);
+}
+
+/*
+ * findDependentObjects - find all objects that depend on 'object'
+ *
+ * For every object that depends on the starting object, acquire a deletion
+ * lock on the object, add it to targetObjects (if not already there),
+ * and recursively find objects that depend on it. An object's dependencies
+ * will be placed into targetObjects before the object itself; this means
+ * that the finished list's order represents a safe deletion order.
+ *
+ * The caller must already have a deletion lock on 'object' itself,
+ * but must not have added it to targetObjects. (Note: there are corner
+ * cases where we won't add the object either, and will also release the
+ * caller-taken lock. This is a bit ugly, but the API is set up this way
+ * to allow easy rechecking of an object's liveness after we lock it. See
+ * notes within the function.)
+ *
+ * When dropping a whole object (subId = 0), we find dependencies for
+ * its sub-objects too.
+ *
+ * object: the object to add to targetObjects and find dependencies on
+ * objflags: flags to be ORed into the object's targetObjects entry
+ * flags: PERFORM_DELETION_xxx flags for the deletion operation as a whole
+ * stack: list of objects being visited in current recursion; topmost item
+ * is the object that we recursed from (NULL for external callers)
+ * targetObjects: list of objects that are scheduled to be deleted
+ * pendingObjects: list of other objects slated for destruction, but
+ * not necessarily in targetObjects yet (can be NULL if none)
+ * *depRel: already opened pg_depend relation
+ *
+ * Note: objflags describes the reason for visiting this particular object
+ * at this time, and is not passed down when recursing. The flags argument
+ * is passed down, since it describes what we're doing overall.
+ */
+static void
+findDependentObjects(const ObjectAddress *object,
+ int objflags,
+ int flags,
+ ObjectAddressStack *stack,
+ ObjectAddresses *targetObjects,
+ const ObjectAddresses *pendingObjects,
+ Relation *depRel)
+{
+ ScanKeyData key[3];
+ int nkeys;
+ SysScanDesc scan;
+ HeapTuple tup;
+ ObjectAddress otherObject;
+ ObjectAddress owningObject;
+ ObjectAddress partitionObject;
+ ObjectAddressAndFlags *dependentObjects;
+ int numDependentObjects;
+ int maxDependentObjects;
+ ObjectAddressStack mystack;
+ ObjectAddressExtra extra;
+
+ /*
+ * If the target object is already being visited in an outer recursion
+ * level, just report the current objflags back to that level and exit.
+ * This is needed to avoid infinite recursion in the face of circular
+ * dependencies.
+ *
+ * The stack check alone would result in dependency loops being broken at
+ * an arbitrary point, ie, the first member object of the loop to be
+ * visited is the last one to be deleted. This is obviously unworkable.
+ * However, the check for internal dependency below guarantees that we
+ * will not break a loop at an internal dependency: if we enter the loop
+ * at an "owned" object we will switch and start at the "owning" object
+ * instead. We could probably hack something up to avoid breaking at an
+ * auto dependency, too, if we had to. However there are no known cases
+ * where that would be necessary.
+ */
+ if (stack_address_present_add_flags(object, objflags, stack))
+ return;
+
+ /*
+ * It's also possible that the target object has already been completely
+ * processed and put into targetObjects. If so, again we just add the
+ * specified objflags to its entry and return.
+ *
+ * (Note: in these early-exit cases we could release the caller-taken
+ * lock, since the object is presumably now locked multiple times; but it
+ * seems not worth the cycles.)
+ */
+ if (object_address_present_add_flags(object, objflags, targetObjects))
+ return;
+
+ /*
+ * The target object might be internally dependent on some other object
+ * (its "owner"), and/or be a member of an extension (also considered its
+ * owner). If so, and if we aren't recursing from the owning object, we
+ * have to transform this deletion request into a deletion request of the
+ * owning object. (We'll eventually recurse back to this object, but the
+ * owning object has to be visited first so it will be deleted after.) The
+ * way to find out about this is to scan the pg_depend entries that show
+ * what this object depends on.
+ */
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+ if (object->objectSubId != 0)
+ {
+ /* Consider only dependencies of this sub-object */
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(object->objectSubId));
+ nkeys = 3;
+ }
+ else
+ {
+ /* Consider dependencies of this object and any sub-objects it has */
+ nkeys = 2;
+ }
+
+ scan = systable_beginscan(*depRel, DependDependerIndexId, true,
+ NULL, nkeys, key);
+
+ /* initialize variables that loop may fill */
+ memset(&owningObject, 0, sizeof(owningObject));
+ memset(&partitionObject, 0, sizeof(partitionObject));
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
+
+ otherObject.classId = foundDep->refclassid;
+ otherObject.objectId = foundDep->refobjid;
+ otherObject.objectSubId = foundDep->refobjsubid;
+
+ /*
+ * When scanning dependencies of a whole object, we may find rows
+ * linking sub-objects of the object to the object itself. (Normally,
+ * such a dependency is implicit, but we must make explicit ones in
+ * some cases involving partitioning.) We must ignore such rows to
+ * avoid infinite recursion.
+ */
+ if (otherObject.classId == object->classId &&
+ otherObject.objectId == object->objectId &&
+ object->objectSubId == 0)
+ continue;
+
+ switch (foundDep->deptype)
+ {
+ case DEPENDENCY_NORMAL:
+ case DEPENDENCY_AUTO:
+ case DEPENDENCY_AUTO_EXTENSION:
+ /* no problem */
+ break;
+
+ case DEPENDENCY_EXTENSION:
+
+ /*
+ * If told to, ignore EXTENSION dependencies altogether. This
+ * flag is normally used to prevent dropping extensions during
+ * temporary-object cleanup, even if a temp object was created
+ * during an extension script.
+ */
+ if (flags & PERFORM_DELETION_SKIP_EXTENSIONS)
+ break;
+
+ /*
+ * If the other object is the extension currently being
+ * created/altered, ignore this dependency and continue with
+ * the deletion. This allows dropping of an extension's
+ * objects within the extension's scripts, as well as corner
+ * cases such as dropping a transient object created within
+ * such a script.
+ */
+ if (creating_extension &&
+ otherObject.classId == ExtensionRelationId &&
+ otherObject.objectId == CurrentExtensionObject)
+ break;
+
+ /* Otherwise, treat this like an internal dependency */
+ /* FALL THRU */
+
+ case DEPENDENCY_INTERNAL:
+
+ /*
+ * This object is part of the internal implementation of
+ * another object, or is part of the extension that is the
+ * other object. We have three cases:
+ *
+ * 1. At the outermost recursion level, we must disallow the
+ * DROP. However, if the owning object is listed in
+ * pendingObjects, just release the caller's lock and return;
+ * we'll eventually complete the DROP when we reach that entry
+ * in the pending list.
+ *
+ * Note: the above statement is true only if this pg_depend
+ * entry still exists by then; in principle, therefore, we
+ * could miss deleting an item the user told us to delete.
+ * However, no inconsistency can result: since we're at outer
+ * level, there is no object depending on this one.
+ */
+ if (stack == NULL)
+ {
+ if (pendingObjects &&
+ object_address_present(&otherObject, pendingObjects))
+ {
+ systable_endscan(scan);
+ /* need to release caller's lock; see notes below */
+ ReleaseDeletionLock(object);
+ return;
+ }
+
+ /*
+ * We postpone actually issuing the error message until
+ * after this loop, so that we can make the behavior
+ * independent of the ordering of pg_depend entries, at
+ * least if there's not more than one INTERNAL and one
+ * EXTENSION dependency. (If there's more, we'll complain
+ * about a random one of them.) Prefer to complain about
+ * EXTENSION, since that's generally a more important
+ * dependency.
+ */
+ if (!OidIsValid(owningObject.classId) ||
+ foundDep->deptype == DEPENDENCY_EXTENSION)
+ owningObject = otherObject;
+ break;
+ }
+
+ /*
+ * 2. When recursing from the other end of this dependency,
+ * it's okay to continue with the deletion. This holds when
+ * recursing from a whole object that includes the nominal
+ * other end as a component, too. Since there can be more
+ * than one "owning" object, we have to allow matches that are
+ * more than one level down in the stack.
+ */
+ if (stack_address_present_add_flags(&otherObject, 0, stack))
+ break;
+
+ /*
+ * 3. Not all the owning objects have been visited, so
+ * transform this deletion request into a delete of this
+ * owning object.
+ *
+ * First, release caller's lock on this object and get
+ * deletion lock on the owning object. (We must release
+ * caller's lock to avoid deadlock against a concurrent
+ * deletion of the owning object.)
+ */
+ ReleaseDeletionLock(object);
+ AcquireDeletionLock(&otherObject, 0);
+
+ /*
+ * The owning object might have been deleted while we waited
+ * to lock it; if so, neither it nor the current object are
+ * interesting anymore. We test this by checking the
+ * pg_depend entry (see notes below).
+ */
+ if (!systable_recheck_tuple(scan, tup))
+ {
+ systable_endscan(scan);
+ ReleaseDeletionLock(&otherObject);
+ return;
+ }
+
+ /*
+ * One way or the other, we're done with the scan; might as
+ * well close it down before recursing, to reduce peak
+ * resource consumption.
+ */
+ systable_endscan(scan);
+
+ /*
+ * Okay, recurse to the owning object instead of proceeding.
+ *
+ * We do not need to stack the current object; we want the
+ * traversal order to be as if the original reference had
+ * linked to the owning object instead of this one.
+ *
+ * The dependency type is a "reverse" dependency: we need to
+ * delete the owning object if this one is to be deleted, but
+ * this linkage is never a reason for an automatic deletion.
+ */
+ findDependentObjects(&otherObject,
+ DEPFLAG_REVERSE,
+ flags,
+ stack,
+ targetObjects,
+ pendingObjects,
+ depRel);
+
+ /*
+ * The current target object should have been added to
+ * targetObjects while processing the owning object; but it
+ * probably got only the flag bits associated with the
+ * dependency we're looking at. We need to add the objflags
+ * that were passed to this recursion level, too, else we may
+ * get a bogus failure in reportDependentObjects (if, for
+ * example, we were called due to a partition dependency).
+ *
+ * If somehow the current object didn't get scheduled for
+ * deletion, bleat. (That would imply that somebody deleted
+ * this dependency record before the recursion got to it.)
+ * Another idea would be to reacquire lock on the current
+ * object and resume trying to delete it, but it seems not
+ * worth dealing with the race conditions inherent in that.
+ */
+ if (!object_address_present_add_flags(object, objflags,
+ targetObjects))
+ elog(ERROR, "deletion of owning object %s failed to delete %s",
+ getObjectDescription(&otherObject),
+ getObjectDescription(object));
+
+ /* And we're done here. */
+ return;
+
+ case DEPENDENCY_PARTITION_PRI:
+
+ /*
+ * Remember that this object has a partition-type dependency.
+ * After the dependency scan, we'll complain if we didn't find
+ * a reason to delete one of its partition dependencies.
+ */
+ objflags |= DEPFLAG_IS_PART;
+
+ /*
+ * Also remember the primary partition owner, for error
+ * messages. If there are multiple primary owners (which
+ * there should not be), we'll report a random one of them.
+ */
+ partitionObject = otherObject;
+ break;
+
+ case DEPENDENCY_PARTITION_SEC:
+
+ /*
+ * Only use secondary partition owners in error messages if we
+ * find no primary owner (which probably shouldn't happen).
+ */
+ if (!(objflags & DEPFLAG_IS_PART))
+ partitionObject = otherObject;
+
+ /*
+ * Remember that this object has a partition-type dependency.
+ * After the dependency scan, we'll complain if we didn't find
+ * a reason to delete one of its partition dependencies.
+ */
+ objflags |= DEPFLAG_IS_PART;
+ break;
+
+ case DEPENDENCY_PIN:
+
+ /*
+ * Should not happen; PIN dependencies should have zeroes in
+ * the depender fields...
+ */
+ elog(ERROR, "incorrect use of PIN dependency with %s",
+ getObjectDescription(object));
+ break;
+ default:
+ elog(ERROR, "unrecognized dependency type '%c' for %s",
+ foundDep->deptype, getObjectDescription(object));
+ break;
+ }
+ }
+
+ systable_endscan(scan);
+
+ /*
+ * If we found an INTERNAL or EXTENSION dependency when we're at outer
+ * level, complain about it now. If we also found a PARTITION dependency,
+ * we prefer to report the PARTITION dependency. This is arbitrary but
+ * seems to be more useful in practice.
+ */
+ if (OidIsValid(owningObject.classId))
+ {
+ char *otherObjDesc;
+
+ if (OidIsValid(partitionObject.classId))
+ otherObjDesc = getObjectDescription(&partitionObject);
+ else
+ otherObjDesc = getObjectDescription(&owningObject);
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+ errmsg("cannot drop %s because %s requires it",
+ getObjectDescription(object), otherObjDesc),
+ errhint("You can drop %s instead.", otherObjDesc)));
+ }
+
+ /*
+ * Next, identify all objects that directly depend on the current object.
+ * To ensure predictable deletion order, we collect them up in
+ * dependentObjects and sort the list before actually recursing. (The
+ * deletion order would be valid in any case, but doing this ensures
+ * consistent output from DROP CASCADE commands, which is helpful for
+ * regression testing.)
+ */
+ maxDependentObjects = 128; /* arbitrary initial allocation */
+ dependentObjects = (ObjectAddressAndFlags *)
+ palloc(maxDependentObjects * sizeof(ObjectAddressAndFlags));
+ numDependentObjects = 0;
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+ if (object->objectSubId != 0)
+ {
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_refobjsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(object->objectSubId));
+ nkeys = 3;
+ }
+ else
+ nkeys = 2;
+
+ scan = systable_beginscan(*depRel, DependReferenceIndexId, true,
+ NULL, nkeys, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
+ int subflags;
+
+ otherObject.classId = foundDep->classid;
+ otherObject.objectId = foundDep->objid;
+ otherObject.objectSubId = foundDep->objsubid;
+
+ /*
+ * If what we found is a sub-object of the current object, just ignore
+ * it. (Normally, such a dependency is implicit, but we must make
+ * explicit ones in some cases involving partitioning.)
+ */
+ if (otherObject.classId == object->classId &&
+ otherObject.objectId == object->objectId &&
+ object->objectSubId == 0)
+ continue;
+
+ /*
+ * Must lock the dependent object before recursing to it.
+ */
+ AcquireDeletionLock(&otherObject, 0);
+
+ /*
+ * The dependent object might have been deleted while we waited to
+ * lock it; if so, we don't need to do anything more with it. We can
+ * test this cheaply and independently of the object's type by seeing
+ * if the pg_depend tuple we are looking at is still live. (If the
+ * object got deleted, the tuple would have been deleted too.)
+ */
+ if (!systable_recheck_tuple(scan, tup))
+ {
+ /* release the now-useless lock */
+ ReleaseDeletionLock(&otherObject);
+ /* and continue scanning for dependencies */
+ continue;
+ }
+
+ /*
+ * We do need to delete it, so identify objflags to be passed down,
+ * which depend on the dependency type.
+ */
+ switch (foundDep->deptype)
+ {
+ case DEPENDENCY_NORMAL:
+ subflags = DEPFLAG_NORMAL;
+ break;
+ case DEPENDENCY_AUTO:
+ case DEPENDENCY_AUTO_EXTENSION:
+ subflags = DEPFLAG_AUTO;
+ break;
+ case DEPENDENCY_INTERNAL:
+ subflags = DEPFLAG_INTERNAL;
+ break;
+ case DEPENDENCY_PARTITION_PRI:
+ case DEPENDENCY_PARTITION_SEC:
+ subflags = DEPFLAG_PARTITION;
+ break;
+ case DEPENDENCY_EXTENSION:
+ subflags = DEPFLAG_EXTENSION;
+ break;
+ case DEPENDENCY_PIN:
+
+ /*
+ * For a PIN dependency we just ereport immediately; there
+ * won't be any others to report.
+ */
+ ereport(ERROR,
+ (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+ errmsg("cannot drop %s because it is required by the database system",
+ getObjectDescription(object))));
+ subflags = 0; /* keep compiler quiet */
+ break;
+ default:
+ elog(ERROR, "unrecognized dependency type '%c' for %s",
+ foundDep->deptype, getObjectDescription(object));
+ subflags = 0; /* keep compiler quiet */
+ break;
+ }
+
+ /* And add it to the pending-objects list */
+ if (numDependentObjects >= maxDependentObjects)
+ {
+ /* enlarge array if needed */
+ maxDependentObjects *= 2;
+ dependentObjects = (ObjectAddressAndFlags *)
+ repalloc(dependentObjects,
+ maxDependentObjects * sizeof(ObjectAddressAndFlags));
+ }
+
+ dependentObjects[numDependentObjects].obj = otherObject;
+ dependentObjects[numDependentObjects].subflags = subflags;
+ numDependentObjects++;
+ }
+
+ systable_endscan(scan);
+
+ /*
+ * Now we can sort the dependent objects into a stable visitation order.
+ * It's safe to use object_address_comparator here since the obj field is
+ * first within ObjectAddressAndFlags.
+ */
+ if (numDependentObjects > 1)
+ qsort((void *) dependentObjects, numDependentObjects,
+ sizeof(ObjectAddressAndFlags),
+ object_address_comparator);
+
+ /*
+ * Now recurse to the dependent objects. We must visit them first since
+ * they have to be deleted before the current object.
+ */
+ mystack.object = object; /* set up a new stack level */
+ mystack.flags = objflags;
+ mystack.next = stack;
+
+ for (int i = 0; i < numDependentObjects; i++)
+ {
+ ObjectAddressAndFlags *depObj = dependentObjects + i;
+
+ findDependentObjects(&depObj->obj,
+ depObj->subflags,
+ flags,
+ &mystack,
+ targetObjects,
+ pendingObjects,
+ depRel);
+ }
+
+ pfree(dependentObjects);
+
+ /*
+ * Finally, we can add the target object to targetObjects. Be careful to
+ * include any flags that were passed back down to us from inner recursion
+ * levels. Record the "dependee" as being either the most important
+ * partition owner if there is one, else the object we recursed from, if
+ * any. (The logic in reportDependentObjects() is such that it can only
+ * need one of those objects.)
+ */
+ extra.flags = mystack.flags;
+ if (extra.flags & DEPFLAG_IS_PART)
+ extra.dependee = partitionObject;
+ else if (stack)
+ extra.dependee = *stack->object;
+ else
+ memset(&extra.dependee, 0, sizeof(extra.dependee));
+ add_exact_object_address_extra(object, &extra, targetObjects);
+}
+
+/*
+ * reportDependentObjects - report about dependencies, and fail if RESTRICT
+ *
+ * Tell the user about dependent objects that we are going to delete
+ * (or would need to delete, but are prevented by RESTRICT mode);
+ * then error out if there are any and it's not CASCADE mode.
+ *
+ * targetObjects: list of objects that are scheduled to be deleted
+ * behavior: RESTRICT or CASCADE
+ * flags: other flags for the deletion operation
+ * origObject: base object of deletion, or NULL if not available
+ * (the latter case occurs in DROP OWNED)
+ */
+static void
+reportDependentObjects(const ObjectAddresses *targetObjects,
+ DropBehavior behavior,
+ int flags,
+ const ObjectAddress *origObject)
+{
+ int msglevel = (flags & PERFORM_DELETION_QUIETLY) ? DEBUG2 : NOTICE;
+ bool ok = true;
+ StringInfoData clientdetail;
+ StringInfoData logdetail;
+ int numReportedClient = 0;
+ int numNotReportedClient = 0;
+ int i;
+
+ /*
+ * If we need to delete any partition-dependent objects, make sure that
+ * we're deleting at least one of their partition dependencies, too. That
+ * can be detected by checking that we reached them by a PARTITION
+ * dependency at some point.
+ *
+ * We just report the first such object, as in most cases the only way to
+ * trigger this complaint is to explicitly try to delete one partition of
+ * a partitioned object.
+ */
+ for (i = 0; i < targetObjects->numrefs; i++)
+ {
+ const ObjectAddressExtra *extra = &targetObjects->extras[i];
+
+ if ((extra->flags & DEPFLAG_IS_PART) &&
+ !(extra->flags & DEPFLAG_PARTITION))
+ {
+ const ObjectAddress *object = &targetObjects->refs[i];
+ char *otherObjDesc = getObjectDescription(&extra->dependee);
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+ errmsg("cannot drop %s because %s requires it",
+ getObjectDescription(object), otherObjDesc),
+ errhint("You can drop %s instead.", otherObjDesc)));
+ }
+ }
+
+ /*
+ * If no error is to be thrown, and the msglevel is too low to be shown to
+ * either client or server log, there's no need to do any of the rest of
+ * the work.
+ *
+ * Note: this code doesn't know all there is to be known about elog
+ * levels, but it works for NOTICE and DEBUG2, which are the only values
+ * msglevel can currently have. We also assume we are running in a normal
+ * operating environment.
+ */
+ if (behavior == DROP_CASCADE &&
+ msglevel < client_min_messages &&
+ (msglevel < log_min_messages || log_min_messages == LOG))
+ return;
+
+ /*
+ * We limit the number of dependencies reported to the client to
+ * MAX_REPORTED_DEPS, since client software may not deal well with
+ * enormous error strings. The server log always gets a full report.
+ */
+#define MAX_REPORTED_DEPS 100
+
+ initStringInfo(&clientdetail);
+ initStringInfo(&logdetail);
+
+ /*
+ * We process the list back to front (ie, in dependency order not deletion
+ * order), since this makes for a more understandable display.
+ */
+ for (i = targetObjects->numrefs - 1; i >= 0; i--)
+ {
+ const ObjectAddress *obj = &targetObjects->refs[i];
+ const ObjectAddressExtra *extra = &targetObjects->extras[i];
+ char *objDesc;
+
+ /* Ignore the original deletion target(s) */
+ if (extra->flags & DEPFLAG_ORIGINAL)
+ continue;
+
+ /* Also ignore sub-objects; we'll report the whole object elsewhere */
+ if (extra->flags & DEPFLAG_SUBOBJECT)
+ continue;
+
+ objDesc = getObjectDescription(obj);
+
+ /*
+ * If, at any stage of the recursive search, we reached the object via
+ * an AUTO, INTERNAL, PARTITION, or EXTENSION dependency, then it's
+ * okay to delete it even in RESTRICT mode.
+ */
+ if (extra->flags & (DEPFLAG_AUTO |
+ DEPFLAG_INTERNAL |
+ DEPFLAG_PARTITION |
+ DEPFLAG_EXTENSION))
+ {
+ /*
+ * auto-cascades are reported at DEBUG2, not msglevel. We don't
+ * try to combine them with the regular message because the
+ * results are too confusing when client_min_messages and
+ * log_min_messages are different.
+ */
+ ereport(DEBUG2,
+ (errmsg("drop auto-cascades to %s",
+ objDesc)));
+ }
+ else if (behavior == DROP_RESTRICT)
+ {
+ char *otherDesc = getObjectDescription(&extra->dependee);
+
+ if (numReportedClient < MAX_REPORTED_DEPS)
+ {
+ /* separate entries with a newline */
+ if (clientdetail.len != 0)
+ appendStringInfoChar(&clientdetail, '\n');
+ appendStringInfo(&clientdetail, _("%s depends on %s"),
+ objDesc, otherDesc);
+ numReportedClient++;
+ }
+ else
+ numNotReportedClient++;
+ /* separate entries with a newline */
+ if (logdetail.len != 0)
+ appendStringInfoChar(&logdetail, '\n');
+ appendStringInfo(&logdetail, _("%s depends on %s"),
+ objDesc, otherDesc);
+ pfree(otherDesc);
+ ok = false;
+ }
+ else
+ {
+ if (numReportedClient < MAX_REPORTED_DEPS)
+ {
+ /* separate entries with a newline */
+ if (clientdetail.len != 0)
+ appendStringInfoChar(&clientdetail, '\n');
+ appendStringInfo(&clientdetail, _("drop cascades to %s"),
+ objDesc);
+ numReportedClient++;
+ }
+ else
+ numNotReportedClient++;
+ /* separate entries with a newline */
+ if (logdetail.len != 0)
+ appendStringInfoChar(&logdetail, '\n');
+ appendStringInfo(&logdetail, _("drop cascades to %s"),
+ objDesc);
+ }
+
+ pfree(objDesc);
+ }
+
+ if (numNotReportedClient > 0)
+ appendStringInfo(&clientdetail, ngettext("\nand %d other object "
+ "(see server log for list)",
+ "\nand %d other objects "
+ "(see server log for list)",
+ numNotReportedClient),
+ numNotReportedClient);
+
+ if (!ok)
+ {
+ if (origObject)
+ ereport(ERROR,
+ (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+ errmsg("cannot drop %s because other objects depend on it",
+ getObjectDescription(origObject)),
+ errdetail("%s", clientdetail.data),
+ errdetail_log("%s", logdetail.data),
+ errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+ errmsg("cannot drop desired object(s) because other objects depend on them"),
+ errdetail("%s", clientdetail.data),
+ errdetail_log("%s", logdetail.data),
+ errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
+ }
+ else if (numReportedClient > 1)
+ {
+ ereport(msglevel,
+ /* translator: %d always has a value larger than 1 */
+ (errmsg_plural("drop cascades to %d other object",
+ "drop cascades to %d other objects",
+ numReportedClient + numNotReportedClient,
+ numReportedClient + numNotReportedClient),
+ errdetail("%s", clientdetail.data),
+ errdetail_log("%s", logdetail.data)));
+ }
+ else if (numReportedClient == 1)
+ {
+ /* we just use the single item as-is */
+ ereport(msglevel,
+ (errmsg_internal("%s", clientdetail.data)));
+ }
+
+ pfree(clientdetail.data);
+ pfree(logdetail.data);
+}
+
+/*
+ * deleteOneObject: delete a single object for performDeletion.
+ *
+ * *depRel is the already-open pg_depend relation.
+ */
+static void
+deleteOneObject(const ObjectAddress *object, Relation *depRel, int flags)
+{
+ ScanKeyData key[3];
+ int nkeys;
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* DROP hook of the objects being removed */
+ InvokeObjectDropHookArg(object->classId, object->objectId,
+ object->objectSubId, flags);
+
+ /*
+ * Close depRel if we are doing a drop concurrently. The object deletion
+ * subroutine will commit the current transaction, so we can't keep the
+ * relation open across doDeletion().
+ */
+ if (flags & PERFORM_DELETION_CONCURRENTLY)
+ table_close(*depRel, RowExclusiveLock);
+
+ /*
+ * Delete the object itself, in an object-type-dependent way.
+ *
+ * We used to do this after removing the outgoing dependency links, but it
+ * seems just as reasonable to do it beforehand. In the concurrent case
+ * we *must* do it in this order, because we can't make any transactional
+ * updates before calling doDeletion() --- they'd get committed right
+ * away, which is not cool if the deletion then fails.
+ */
+ doDeletion(object, flags);
+
+ /*
+ * Reopen depRel if we closed it above
+ */
+ if (flags & PERFORM_DELETION_CONCURRENTLY)
+ *depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ /*
+ * Now remove any pg_depend records that link from this object to others.
+ * (Any records linking to this object should be gone already.)
+ *
+ * When dropping a whole object (subId = 0), remove all pg_depend records
+ * for its sub-objects too.
+ */
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+ if (object->objectSubId != 0)
+ {
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(object->objectSubId));
+ nkeys = 3;
+ }
+ else
+ nkeys = 2;
+
+ scan = systable_beginscan(*depRel, DependDependerIndexId, true,
+ NULL, nkeys, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ CatalogTupleDelete(*depRel, &tup->t_self);
+ }
+
+ systable_endscan(scan);
+
+ /*
+ * Delete shared dependency references related to this object. Again, if
+ * subId = 0, remove records for sub-objects too.
+ */
+ deleteSharedDependencyRecordsFor(object->classId, object->objectId,
+ object->objectSubId);
+
+
+ /*
+ * Delete any comments, security labels, or initial privileges associated
+ * with this object. (This is a convenient place to do these things,
+ * rather than having every object type know to do it.)
+ */
+ DeleteComments(object->objectId, object->classId, object->objectSubId);
+ DeleteSecurityLabel(object);
+ DeleteInitPrivs(object);
+
+ /*
+ * CommandCounterIncrement here to ensure that preceding changes are all
+ * visible to the next deletion step.
+ */
+ CommandCounterIncrement();
+
+ /*
+ * And we're done!
+ */
+}
+
+/*
+ * doDeletion: actually delete a single object
+ */
+static void
+doDeletion(const ObjectAddress *object, int flags)
+{
+ switch (getObjectClass(object))
+ {
+ case OCLASS_CLASS:
+ {
+ char relKind = get_rel_relkind(object->objectId);
+
+ if (relKind == RELKIND_INDEX ||
+ relKind == RELKIND_PARTITIONED_INDEX)
+ {
+ bool concurrent = ((flags & PERFORM_DELETION_CONCURRENTLY) != 0);
+ bool concurrent_lock_mode = ((flags & PERFORM_DELETION_CONCURRENT_LOCK) != 0);
+
+ Assert(object->objectSubId == 0);
+ index_drop(object->objectId, concurrent, concurrent_lock_mode);
+ }
+ else
+ {
+ if (object->objectSubId != 0)
+ RemoveAttributeById(object->objectId,
+ object->objectSubId);
+ else
+ heap_drop_with_catalog(object->objectId);
+ }
+
+ /*
+ * for a sequence, in addition to dropping the heap, also
+ * delete pg_sequence tuple
+ */
+ if (relKind == RELKIND_SEQUENCE)
+ DeleteSequenceTuple(object->objectId);
+ break;
+ }
+
+ case OCLASS_PROC:
+ RemoveFunctionById(object->objectId);
+ break;
+
+ case OCLASS_TYPE:
+ RemoveTypeById(object->objectId);
+ break;
+
+ case OCLASS_CAST:
+ DropCastById(object->objectId);
+ break;
+
+ case OCLASS_COLLATION:
+ RemoveCollationById(object->objectId);
+ break;
+
+ case OCLASS_CONSTRAINT:
+ RemoveConstraintById(object->objectId);
+ break;
+
+ case OCLASS_CONVERSION:
+ RemoveConversionById(object->objectId);
+ break;
+
+ case OCLASS_DEFAULT:
+ RemoveAttrDefaultById(object->objectId);
+ break;
+
+ case OCLASS_LANGUAGE:
+ DropProceduralLanguageById(object->objectId);
+ break;
+
+ case OCLASS_LARGEOBJECT:
+ LargeObjectDrop(object->objectId);
+ break;
+
+ case OCLASS_OPERATOR:
+ RemoveOperatorById(object->objectId);
+ break;
+
+ case OCLASS_OPCLASS:
+ RemoveOpClassById(object->objectId);
+ break;
+
+ case OCLASS_OPFAMILY:
+ RemoveOpFamilyById(object->objectId);
+ break;
+
+ case OCLASS_AM:
+ RemoveAccessMethodById(object->objectId);
+ break;
+
+ case OCLASS_AMOP:
+ RemoveAmOpEntryById(object->objectId);
+ break;
+
+ case OCLASS_AMPROC:
+ RemoveAmProcEntryById(object->objectId);
+ break;
+
+ case OCLASS_REWRITE:
+ RemoveRewriteRuleById(object->objectId);
+ break;
+
+ case OCLASS_TRIGGER:
+ RemoveTriggerById(object->objectId);
+ break;
+
+ case OCLASS_SCHEMA:
+ RemoveSchemaById(object->objectId);
+ break;
+
+ case OCLASS_STATISTIC_EXT:
+ RemoveStatisticsById(object->objectId);
+ break;
+
+ case OCLASS_TSPARSER:
+ RemoveTSParserById(object->objectId);
+ break;
+
+ case OCLASS_TSDICT:
+ RemoveTSDictionaryById(object->objectId);
+ break;
+
+ case OCLASS_TSTEMPLATE:
+ RemoveTSTemplateById(object->objectId);
+ break;
+
+ case OCLASS_TSCONFIG:
+ RemoveTSConfigurationById(object->objectId);
+ break;
+
+ /*
+ * OCLASS_ROLE, OCLASS_DATABASE, OCLASS_TBLSPACE intentionally not
+ * handled here
+ */
+
+ case OCLASS_FDW:
+ RemoveForeignDataWrapperById(object->objectId);
+ break;
+
+ case OCLASS_FOREIGN_SERVER:
+ RemoveForeignServerById(object->objectId);
+ break;
+
+ case OCLASS_USER_MAPPING:
+ RemoveUserMappingById(object->objectId);
+ break;
+
+ case OCLASS_DEFACL:
+ RemoveDefaultACLById(object->objectId);
+ break;
+
+ case OCLASS_EXTENSION:
+ RemoveExtensionById(object->objectId);
+ break;
+
+ case OCLASS_EVENT_TRIGGER:
+ RemoveEventTriggerById(object->objectId);
+ break;
+
+ case OCLASS_POLICY:
+ RemovePolicyById(object->objectId);
+ break;
+
+ case OCLASS_PUBLICATION:
+ RemovePublicationById(object->objectId);
+ break;
+
+ case OCLASS_PUBLICATION_REL:
+ RemovePublicationRelById(object->objectId);
+ break;
+
+ case OCLASS_TRANSFORM:
+ DropTransformById(object->objectId);
+ break;
+
+ /*
+ * These global object types are not supported here.
+ */
+ case OCLASS_ROLE:
+ case OCLASS_DATABASE:
+ case OCLASS_TBLSPACE:
+ case OCLASS_SUBSCRIPTION:
+ elog(ERROR, "global objects cannot be deleted by doDeletion");
+ break;
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
+ }
+}
+
+/*
+ * AcquireDeletionLock - acquire a suitable lock for deleting an object
+ *
+ * Accepts the same flags as performDeletion (though currently only
+ * PERFORM_DELETION_CONCURRENTLY does anything).
+ *
+ * We use LockRelation for relations, LockDatabaseObject for everything
+ * else. Shared-across-databases objects are not currently supported
+ * because no caller cares, but could be modified to use LockSharedObject.
+ */
+void
+AcquireDeletionLock(const ObjectAddress *object, int flags)
+{
+ if (object->classId == RelationRelationId)
+ {
+ /*
+ * In DROP INDEX CONCURRENTLY, take only ShareUpdateExclusiveLock on
+ * the index for the moment. index_drop() will promote the lock once
+ * it's safe to do so. In all other cases we need full exclusive
+ * lock.
+ */
+ if (flags & PERFORM_DELETION_CONCURRENTLY)
+ LockRelationOid(object->objectId, ShareUpdateExclusiveLock);
+ else
+ LockRelationOid(object->objectId, AccessExclusiveLock);
+ }
+ else
+ {
+ /* assume we should lock the whole object not a sub-object */
+ LockDatabaseObject(object->classId, object->objectId, 0,
+ AccessExclusiveLock);
+ }
+}
+
+/*
+ * ReleaseDeletionLock - release an object deletion lock
+ *
+ * Companion to AcquireDeletionLock.
+ */
+void
+ReleaseDeletionLock(const ObjectAddress *object)
+{
+ if (object->classId == RelationRelationId)
+ UnlockRelationOid(object->objectId, AccessExclusiveLock);
+ else
+ /* assume we should lock the whole object not a sub-object */
+ UnlockDatabaseObject(object->classId, object->objectId, 0,
+ AccessExclusiveLock);
+}
+
+/*
+ * recordDependencyOnExpr - find expression dependencies
+ *
+ * This is used to find the dependencies of rules, constraint expressions,
+ * etc.
+ *
+ * Given an expression or query in node-tree form, find all the objects
+ * it refers to (tables, columns, operators, functions, etc). Record
+ * a dependency of the specified type from the given depender object
+ * to each object mentioned in the expression.
+ *
+ * rtable is the rangetable to be used to interpret Vars with varlevelsup=0.
+ * It can be NIL if no such variables are expected.
+ */
+void
+recordDependencyOnExpr(const ObjectAddress *depender,
+ Node *expr, List *rtable,
+ DependencyType behavior)
+{
+ find_expr_references_context context;
+
+ context.addrs = new_object_addresses();
+
+ /* Set up interpretation for Vars at varlevelsup = 0 */
+ context.rtables = list_make1(rtable);
+
+ /* Scan the expression tree for referenceable objects */
+ find_expr_references_walker(expr, &context);
+
+ /* Remove any duplicates */
+ eliminate_duplicate_dependencies(context.addrs);
+
+ /* And record 'em */
+ recordMultipleDependencies(depender,
+ context.addrs->refs, context.addrs->numrefs,
+ behavior);
+
+ free_object_addresses(context.addrs);
+}
+
+/*
+ * recordDependencyOnSingleRelExpr - find expression dependencies
+ *
+ * As above, but only one relation is expected to be referenced (with
+ * varno = 1 and varlevelsup = 0). Pass the relation OID instead of a
+ * range table. An additional frammish is that dependencies on that
+ * relation's component columns will be marked with 'self_behavior',
+ * whereas 'behavior' is used for everything else; also, if 'reverse_self'
+ * is true, those dependencies are reversed so that the columns are made
+ * to depend on the table not vice versa.
+ *
+ * NOTE: the caller should ensure that a whole-table dependency on the
+ * specified relation is created separately, if one is needed. In particular,
+ * a whole-row Var "relation.*" will not cause this routine to emit any
+ * dependency item. This is appropriate behavior for subexpressions of an
+ * ordinary query, so other cases need to cope as necessary.
+ */
+void
+recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
+ Node *expr, Oid relId,
+ DependencyType behavior,
+ DependencyType self_behavior,
+ bool reverse_self)
+{
+ find_expr_references_context context;
+ RangeTblEntry rte;
+
+ context.addrs = new_object_addresses();
+
+ /* We gin up a rather bogus rangetable list to handle Vars */
+ MemSet(&rte, 0, sizeof(rte));
+ rte.type = T_RangeTblEntry;
+ rte.rtekind = RTE_RELATION;
+ rte.relid = relId;
+ rte.relkind = RELKIND_RELATION; /* no need for exactness here */
+ rte.rellockmode = AccessShareLock;
+
+ context.rtables = list_make1(list_make1(&rte));
+
+ /* Scan the expression tree for referenceable objects */
+ find_expr_references_walker(expr, &context);
+
+ /* Remove any duplicates */
+ eliminate_duplicate_dependencies(context.addrs);
+
+ /* Separate self-dependencies if necessary */
+ if ((behavior != self_behavior || reverse_self) &&
+ context.addrs->numrefs > 0)
+ {
+ ObjectAddresses *self_addrs;
+ ObjectAddress *outobj;
+ int oldref,
+ outrefs;
+
+ self_addrs = new_object_addresses();
+
+ outobj = context.addrs->refs;
+ outrefs = 0;
+ for (oldref = 0; oldref < context.addrs->numrefs; oldref++)
+ {
+ ObjectAddress *thisobj = context.addrs->refs + oldref;
+
+ if (thisobj->classId == RelationRelationId &&
+ thisobj->objectId == relId)
+ {
+ /* Move this ref into self_addrs */
+ add_exact_object_address(thisobj, self_addrs);
+ }
+ else
+ {
+ /* Keep it in context.addrs */
+ *outobj = *thisobj;
+ outobj++;
+ outrefs++;
+ }
+ }
+ context.addrs->numrefs = outrefs;
+
+ /* Record the self-dependencies with the appropriate direction */
+ if (!reverse_self)
+ recordMultipleDependencies(depender,
+ self_addrs->refs, self_addrs->numrefs,
+ self_behavior);
+ else
+ {
+ /* Can't use recordMultipleDependencies, so do it the hard way */
+ int selfref;
+
+ for (selfref = 0; selfref < self_addrs->numrefs; selfref++)
+ {
+ ObjectAddress *thisobj = self_addrs->refs + selfref;
+
+ recordDependencyOn(thisobj, depender, self_behavior);
+ }
+ }
+
+ free_object_addresses(self_addrs);
+ }
+
+ /* Record the external dependencies */
+ recordMultipleDependencies(depender,
+ context.addrs->refs, context.addrs->numrefs,
+ behavior);
+
+ free_object_addresses(context.addrs);
+}
+
+/*
+ * Recursively search an expression tree for object references.
+ *
+ * Note: in many cases we do not need to create dependencies on the datatypes
+ * involved in an expression, because we'll have an indirect dependency via
+ * some other object. For instance Var nodes depend on a column which depends
+ * on the datatype, and OpExpr nodes depend on the operator which depends on
+ * the datatype. However we do need a type dependency if there is no such
+ * indirect dependency, as for example in Const and CoerceToDomain nodes.
+ *
+ * Similarly, we don't need to create dependencies on collations except where
+ * the collation is being freshly introduced to the expression.
+ */
+static bool
+find_expr_references_walker(Node *node,
+ find_expr_references_context *context)
+{
+ if (node == NULL)
+ return false;
+ if (IsA(node, Var))
+ {
+ Var *var = (Var *) node;
+ List *rtable;
+ RangeTblEntry *rte;
+
+ /* Find matching rtable entry, or complain if not found */
+ if (var->varlevelsup >= list_length(context->rtables))
+ elog(ERROR, "invalid varlevelsup %d", var->varlevelsup);
+ rtable = (List *) list_nth(context->rtables, var->varlevelsup);
+ if (var->varno <= 0 || var->varno > list_length(rtable))
+ elog(ERROR, "invalid varno %d", var->varno);
+ rte = rt_fetch(var->varno, rtable);
+
+ /*
+ * A whole-row Var references no specific columns, so adds no new
+ * dependency. (We assume that there is a whole-table dependency
+ * arising from each underlying rangetable entry. While we could
+ * record such a dependency when finding a whole-row Var that
+ * references a relation directly, it's quite unclear how to extend
+ * that to whole-row Vars for JOINs, so it seems better to leave the
+ * responsibility with the range table. Note that this poses some
+ * risks for identifying dependencies of stand-alone expressions:
+ * whole-table references may need to be created separately.)
+ */
+ if (var->varattno == InvalidAttrNumber)
+ return false;
+ if (rte->rtekind == RTE_RELATION)
+ {
+ /* If it's a plain relation, reference this column */
+ add_object_address(OCLASS_CLASS, rte->relid, var->varattno,
+ context->addrs);
+ }
+
+ /*
+ * Vars referencing other RTE types require no additional work. In
+ * particular, a join alias Var can be ignored, because it must
+ * reference a merged USING column. The relevant join input columns
+ * will also be referenced in the join qual, and any type coercion
+ * functions involved in the alias expression will be dealt with when
+ * we scan the RTE itself.
+ */
+ return false;
+ }
+ else if (IsA(node, Const))
+ {
+ Const *con = (Const *) node;
+ Oid objoid;
+
+ /* A constant must depend on the constant's datatype */
+ add_object_address(OCLASS_TYPE, con->consttype, 0,
+ context->addrs);
+
+ /*
+ * We must also depend on the constant's collation: it could be
+ * different from the datatype's, if a CollateExpr was const-folded to
+ * a simple constant. However we can save work in the most common
+ * case where the collation is "default", since we know that's pinned.
+ */
+ if (OidIsValid(con->constcollid) &&
+ con->constcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, con->constcollid, 0,
+ context->addrs);
+
+ /*
+ * If it's a regclass or similar literal referring to an existing
+ * object, add a reference to that object. (Currently, only the
+ * regclass and regconfig cases have any likely use, but we may as
+ * well handle all the OID-alias datatypes consistently.)
+ */
+ if (!con->constisnull)
+ {
+ switch (con->consttype)
+ {
+ case REGPROCOID:
+ case REGPROCEDUREOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists1(PROCOID,
+ ObjectIdGetDatum(objoid)))
+ add_object_address(OCLASS_PROC, objoid, 0,
+ context->addrs);
+ break;
+ case REGOPEROID:
+ case REGOPERATOROID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists1(OPEROID,
+ ObjectIdGetDatum(objoid)))
+ add_object_address(OCLASS_OPERATOR, objoid, 0,
+ context->addrs);
+ break;
+ case REGCLASSOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists1(RELOID,
+ ObjectIdGetDatum(objoid)))
+ add_object_address(OCLASS_CLASS, objoid, 0,
+ context->addrs);
+ break;
+ case REGTYPEOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists1(TYPEOID,
+ ObjectIdGetDatum(objoid)))
+ add_object_address(OCLASS_TYPE, objoid, 0,
+ context->addrs);
+ break;
+ case REGCONFIGOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists1(TSCONFIGOID,
+ ObjectIdGetDatum(objoid)))
+ add_object_address(OCLASS_TSCONFIG, objoid, 0,
+ context->addrs);
+ break;
+ case REGDICTIONARYOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists1(TSDICTOID,
+ ObjectIdGetDatum(objoid)))
+ add_object_address(OCLASS_TSDICT, objoid, 0,
+ context->addrs);
+ break;
+
+ case REGNAMESPACEOID:
+ objoid = DatumGetObjectId(con->constvalue);
+ if (SearchSysCacheExists1(NAMESPACEOID,
+ ObjectIdGetDatum(objoid)))
+ add_object_address(OCLASS_SCHEMA, objoid, 0,
+ context->addrs);
+ break;
+
+ /*
+ * Dependencies for regrole should be shared among all
+ * databases, so explicitly inhibit to have dependencies.
+ */
+ case REGROLEOID:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("constant of the type %s cannot be used here",
+ "regrole")));
+ break;
+ }
+ }
+ return false;
+ }
+ else if (IsA(node, Param))
+ {
+ Param *param = (Param *) node;
+
+ /* A parameter must depend on the parameter's datatype */
+ add_object_address(OCLASS_TYPE, param->paramtype, 0,
+ context->addrs);
+ /* and its collation, just as for Consts */
+ if (OidIsValid(param->paramcollid) &&
+ param->paramcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, param->paramcollid, 0,
+ context->addrs);
+ }
+ else if (IsA(node, FuncExpr))
+ {
+ FuncExpr *funcexpr = (FuncExpr *) node;
+
+ add_object_address(OCLASS_PROC, funcexpr->funcid, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, OpExpr))
+ {
+ OpExpr *opexpr = (OpExpr *) node;
+
+ add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, DistinctExpr))
+ {
+ DistinctExpr *distinctexpr = (DistinctExpr *) node;
+
+ add_object_address(OCLASS_OPERATOR, distinctexpr->opno, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, NullIfExpr))
+ {
+ NullIfExpr *nullifexpr = (NullIfExpr *) node;
+
+ add_object_address(OCLASS_OPERATOR, nullifexpr->opno, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, ScalarArrayOpExpr))
+ {
+ ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node;
+
+ add_object_address(OCLASS_OPERATOR, opexpr->opno, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, Aggref))
+ {
+ Aggref *aggref = (Aggref *) node;
+
+ add_object_address(OCLASS_PROC, aggref->aggfnoid, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, WindowFunc))
+ {
+ WindowFunc *wfunc = (WindowFunc *) node;
+
+ add_object_address(OCLASS_PROC, wfunc->winfnoid, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, SubPlan))
+ {
+ /* Extra work needed here if we ever need this case */
+ elog(ERROR, "already-planned subqueries not supported");
+ }
+ else if (IsA(node, FieldSelect))
+ {
+ FieldSelect *fselect = (FieldSelect *) node;
+ Oid argtype = getBaseType(exprType((Node *) fselect->arg));
+ Oid reltype = get_typ_typrelid(argtype);
+
+ /*
+ * We need a dependency on the specific column named in FieldSelect,
+ * assuming we can identify the pg_class OID for it. (Probably we
+ * always can at the moment, but in future it might be possible for
+ * argtype to be RECORDOID.) If we can make a column dependency then
+ * we shouldn't need a dependency on the column's type; but if we
+ * can't, make a dependency on the type, as it might not appear
+ * anywhere else in the expression.
+ */
+ if (OidIsValid(reltype))
+ add_object_address(OCLASS_CLASS, reltype, fselect->fieldnum,
+ context->addrs);
+ else
+ add_object_address(OCLASS_TYPE, fselect->resulttype, 0,
+ context->addrs);
+ /* the collation might not be referenced anywhere else, either */
+ if (OidIsValid(fselect->resultcollid) &&
+ fselect->resultcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, fselect->resultcollid, 0,
+ context->addrs);
+ }
+ else if (IsA(node, FieldStore))
+ {
+ FieldStore *fstore = (FieldStore *) node;
+ Oid reltype = get_typ_typrelid(fstore->resulttype);
+
+ /* similar considerations to FieldSelect, but multiple column(s) */
+ if (OidIsValid(reltype))
+ {
+ ListCell *l;
+
+ foreach(l, fstore->fieldnums)
+ add_object_address(OCLASS_CLASS, reltype, lfirst_int(l),
+ context->addrs);
+ }
+ else
+ add_object_address(OCLASS_TYPE, fstore->resulttype, 0,
+ context->addrs);
+ }
+ else if (IsA(node, RelabelType))
+ {
+ RelabelType *relab = (RelabelType *) node;
+
+ /* since there is no function dependency, need to depend on type */
+ add_object_address(OCLASS_TYPE, relab->resulttype, 0,
+ context->addrs);
+ /* the collation might not be referenced anywhere else, either */
+ if (OidIsValid(relab->resultcollid) &&
+ relab->resultcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, relab->resultcollid, 0,
+ context->addrs);
+ }
+ else if (IsA(node, CoerceViaIO))
+ {
+ CoerceViaIO *iocoerce = (CoerceViaIO *) node;
+
+ /* since there is no exposed function, need to depend on type */
+ add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0,
+ context->addrs);
+ /* the collation might not be referenced anywhere else, either */
+ if (OidIsValid(iocoerce->resultcollid) &&
+ iocoerce->resultcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, iocoerce->resultcollid, 0,
+ context->addrs);
+ }
+ else if (IsA(node, ArrayCoerceExpr))
+ {
+ ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;
+
+ /* as above, depend on type */
+ add_object_address(OCLASS_TYPE, acoerce->resulttype, 0,
+ context->addrs);
+ /* the collation might not be referenced anywhere else, either */
+ if (OidIsValid(acoerce->resultcollid) &&
+ acoerce->resultcollid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, acoerce->resultcollid, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, ConvertRowtypeExpr))
+ {
+ ConvertRowtypeExpr *cvt = (ConvertRowtypeExpr *) node;
+
+ /* since there is no function dependency, need to depend on type */
+ add_object_address(OCLASS_TYPE, cvt->resulttype, 0,
+ context->addrs);
+ }
+ else if (IsA(node, CollateExpr))
+ {
+ CollateExpr *coll = (CollateExpr *) node;
+
+ add_object_address(OCLASS_COLLATION, coll->collOid, 0,
+ context->addrs);
+ }
+ else if (IsA(node, RowExpr))
+ {
+ RowExpr *rowexpr = (RowExpr *) node;
+
+ add_object_address(OCLASS_TYPE, rowexpr->row_typeid, 0,
+ context->addrs);
+ }
+ else if (IsA(node, RowCompareExpr))
+ {
+ RowCompareExpr *rcexpr = (RowCompareExpr *) node;
+ ListCell *l;
+
+ foreach(l, rcexpr->opnos)
+ {
+ add_object_address(OCLASS_OPERATOR, lfirst_oid(l), 0,
+ context->addrs);
+ }
+ foreach(l, rcexpr->opfamilies)
+ {
+ add_object_address(OCLASS_OPFAMILY, lfirst_oid(l), 0,
+ context->addrs);
+ }
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, CoerceToDomain))
+ {
+ CoerceToDomain *cd = (CoerceToDomain *) node;
+
+ add_object_address(OCLASS_TYPE, cd->resulttype, 0,
+ context->addrs);
+ }
+ else if (IsA(node, NextValueExpr))
+ {
+ NextValueExpr *nve = (NextValueExpr *) node;
+
+ add_object_address(OCLASS_CLASS, nve->seqid, 0,
+ context->addrs);
+ }
+ else if (IsA(node, OnConflictExpr))
+ {
+ OnConflictExpr *onconflict = (OnConflictExpr *) node;
+
+ if (OidIsValid(onconflict->constraint))
+ add_object_address(OCLASS_CONSTRAINT, onconflict->constraint, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, SortGroupClause))
+ {
+ SortGroupClause *sgc = (SortGroupClause *) node;
+
+ add_object_address(OCLASS_OPERATOR, sgc->eqop, 0,
+ context->addrs);
+ if (OidIsValid(sgc->sortop))
+ add_object_address(OCLASS_OPERATOR, sgc->sortop, 0,
+ context->addrs);
+ return false;
+ }
+ else if (IsA(node, WindowClause))
+ {
+ WindowClause *wc = (WindowClause *) node;
+
+ if (OidIsValid(wc->startInRangeFunc))
+ add_object_address(OCLASS_PROC, wc->startInRangeFunc, 0,
+ context->addrs);
+ if (OidIsValid(wc->endInRangeFunc))
+ add_object_address(OCLASS_PROC, wc->endInRangeFunc, 0,
+ context->addrs);
+ if (OidIsValid(wc->inRangeColl) &&
+ wc->inRangeColl != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, wc->inRangeColl, 0,
+ context->addrs);
+ /* fall through to examine substructure */
+ }
+ else if (IsA(node, Query))
+ {
+ /* Recurse into RTE subquery or not-yet-planned sublink subquery */
+ Query *query = (Query *) node;
+ ListCell *lc;
+ bool result;
+
+ /*
+ * Add whole-relation refs for each plain relation mentioned in the
+ * subquery's rtable, and ensure we add refs for any type-coercion
+ * functions used in join alias lists.
+ *
+ * Note: query_tree_walker takes care of recursing into RTE_FUNCTION
+ * RTEs, subqueries, etc, so no need to do that here. But we must
+ * tell it not to visit join alias lists, or we'll add refs for join
+ * input columns whether or not they are actually used in our query.
+ *
+ * Note: we don't need to worry about collations mentioned in
+ * RTE_VALUES or RTE_CTE RTEs, because those must just duplicate
+ * collations referenced in other parts of the Query. We do have to
+ * worry about collations mentioned in RTE_FUNCTION, but we take care
+ * of those when we recurse to the RangeTblFunction node(s).
+ */
+ foreach(lc, query->rtable)
+ {
+ RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
+
+ switch (rte->rtekind)
+ {
+ case RTE_RELATION:
+ add_object_address(OCLASS_CLASS, rte->relid, 0,
+ context->addrs);
+ break;
+ case RTE_JOIN:
+
+ /*
+ * Examine joinaliasvars entries only for merged JOIN
+ * USING columns. Only those entries could contain
+ * type-coercion functions. Also, their join input
+ * columns must be referenced in the join quals, so this
+ * won't accidentally add refs to otherwise-unused join
+ * input columns. (We want to ref the type coercion
+ * functions even if the merged column isn't explicitly
+ * used anywhere, to protect possible expansion of the
+ * join RTE as a whole-row var, and because it seems like
+ * a bad idea to allow dropping a function that's present
+ * in our query tree, whether or not it could get called.)
+ */
+ context->rtables = lcons(query->rtable, context->rtables);
+ for (int i = 0; i < rte->joinmergedcols; i++)
+ {
+ Node *aliasvar = list_nth(rte->joinaliasvars, i);
+
+ if (!IsA(aliasvar, Var))
+ find_expr_references_walker(aliasvar, context);
+ }
+ context->rtables = list_delete_first(context->rtables);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * If the query is an INSERT or UPDATE, we should create a dependency
+ * on each target column, to prevent the specific target column from
+ * being dropped. Although we will visit the TargetEntry nodes again
+ * during query_tree_walker, we won't have enough context to do this
+ * conveniently, so do it here.
+ */
+ if (query->commandType == CMD_INSERT ||
+ query->commandType == CMD_UPDATE)
+ {
+ RangeTblEntry *rte;
+
+ if (query->resultRelation <= 0 ||
+ query->resultRelation > list_length(query->rtable))
+ elog(ERROR, "invalid resultRelation %d",
+ query->resultRelation);
+ rte = rt_fetch(query->resultRelation, query->rtable);
+ if (rte->rtekind == RTE_RELATION)
+ {
+ foreach(lc, query->targetList)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(lc);
+
+ if (tle->resjunk)
+ continue; /* ignore junk tlist items */
+ add_object_address(OCLASS_CLASS, rte->relid, tle->resno,
+ context->addrs);
+ }
+ }
+ }
+
+ /*
+ * Add dependencies on constraints listed in query's constraintDeps
+ */
+ foreach(lc, query->constraintDeps)
+ {
+ add_object_address(OCLASS_CONSTRAINT, lfirst_oid(lc), 0,
+ context->addrs);
+ }
+
+ /* Examine substructure of query */
+ context->rtables = lcons(query->rtable, context->rtables);
+ result = query_tree_walker(query,
+ find_expr_references_walker,
+ (void *) context,
+ QTW_IGNORE_JOINALIASES |
+ QTW_EXAMINE_SORTGROUP);
+ context->rtables = list_delete_first(context->rtables);
+ return result;
+ }
+ else if (IsA(node, SetOperationStmt))
+ {
+ SetOperationStmt *setop = (SetOperationStmt *) node;
+
+ /* we need to look at the groupClauses for operator references */
+ find_expr_references_walker((Node *) setop->groupClauses, context);
+ /* fall through to examine child nodes */
+ }
+ else if (IsA(node, RangeTblFunction))
+ {
+ RangeTblFunction *rtfunc = (RangeTblFunction *) node;
+ ListCell *ct;
+
+ /*
+ * Add refs for any datatypes and collations used in a column
+ * definition list for a RECORD function. (For other cases, it should
+ * be enough to depend on the function itself.)
+ */
+ foreach(ct, rtfunc->funccoltypes)
+ {
+ add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0,
+ context->addrs);
+ }
+ foreach(ct, rtfunc->funccolcollations)
+ {
+ Oid collid = lfirst_oid(ct);
+
+ if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, collid, 0,
+ context->addrs);
+ }
+ }
+ else if (IsA(node, TableFunc))
+ {
+ TableFunc *tf = (TableFunc *) node;
+ ListCell *ct;
+
+ /*
+ * Add refs for the datatypes and collations used in the TableFunc.
+ */
+ foreach(ct, tf->coltypes)
+ {
+ add_object_address(OCLASS_TYPE, lfirst_oid(ct), 0,
+ context->addrs);
+ }
+ foreach(ct, tf->colcollations)
+ {
+ Oid collid = lfirst_oid(ct);
+
+ if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
+ add_object_address(OCLASS_COLLATION, collid, 0,
+ context->addrs);
+ }
+ }
+ else if (IsA(node, TableSampleClause))
+ {
+ TableSampleClause *tsc = (TableSampleClause *) node;
+
+ add_object_address(OCLASS_PROC, tsc->tsmhandler, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+
+ return expression_tree_walker(node, find_expr_references_walker,
+ (void *) context);
+}
+
+/*
+ * Given an array of dependency references, eliminate any duplicates.
+ */
+static void
+eliminate_duplicate_dependencies(ObjectAddresses *addrs)
+{
+ ObjectAddress *priorobj;
+ int oldref,
+ newrefs;
+
+ /*
+ * We can't sort if the array has "extra" data, because there's no way to
+ * keep it in sync. Fortunately that combination of features is not
+ * needed.
+ */
+ Assert(!addrs->extras);
+
+ if (addrs->numrefs <= 1)
+ return; /* nothing to do */
+
+ /* Sort the refs so that duplicates are adjacent */
+ qsort((void *) addrs->refs, addrs->numrefs, sizeof(ObjectAddress),
+ object_address_comparator);
+
+ /* Remove dups */
+ priorobj = addrs->refs;
+ newrefs = 1;
+ for (oldref = 1; oldref < addrs->numrefs; oldref++)
+ {
+ ObjectAddress *thisobj = addrs->refs + oldref;
+
+ if (priorobj->classId == thisobj->classId &&
+ priorobj->objectId == thisobj->objectId)
+ {
+ if (priorobj->objectSubId == thisobj->objectSubId)
+ continue; /* identical, so drop thisobj */
+
+ /*
+ * If we have a whole-object reference and a reference to a part
+ * of the same object, we don't need the whole-object reference
+ * (for example, we don't need to reference both table foo and
+ * column foo.bar). The whole-object reference will always appear
+ * first in the sorted list.
+ */
+ if (priorobj->objectSubId == 0)
+ {
+ /* replace whole ref with partial */
+ priorobj->objectSubId = thisobj->objectSubId;
+ continue;
+ }
+ }
+ /* Not identical, so add thisobj to output set */
+ priorobj++;
+ *priorobj = *thisobj;
+ newrefs++;
+ }
+
+ addrs->numrefs = newrefs;
+}
+
+/*
+ * qsort comparator for ObjectAddress items
+ */
+static int
+object_address_comparator(const void *a, const void *b)
+{
+ const ObjectAddress *obja = (const ObjectAddress *) a;
+ const ObjectAddress *objb = (const ObjectAddress *) b;
+
+ /*
+ * Primary sort key is OID descending. Most of the time, this will result
+ * in putting newer objects before older ones, which is likely to be the
+ * right order to delete in.
+ */
+ if (obja->objectId > objb->objectId)
+ return -1;
+ if (obja->objectId < objb->objectId)
+ return 1;
+
+ /*
+ * Next sort on catalog ID, in case identical OIDs appear in different
+ * catalogs. Sort direction is pretty arbitrary here.
+ */
+ if (obja->classId < objb->classId)
+ return -1;
+ if (obja->classId > objb->classId)
+ return 1;
+
+ /*
+ * Last, sort on object subId.
+ *
+ * We sort the subId as an unsigned int so that 0 (the whole object) will
+ * come first. This is essential for eliminate_duplicate_dependencies,
+ * and is also the best order for findDependentObjects.
+ */
+ if ((unsigned int) obja->objectSubId < (unsigned int) objb->objectSubId)
+ return -1;
+ if ((unsigned int) obja->objectSubId > (unsigned int) objb->objectSubId)
+ return 1;
+ return 0;
+}
+
+/*
+ * Routines for handling an expansible array of ObjectAddress items.
+ *
+ * new_object_addresses: create a new ObjectAddresses array.
+ */
+ObjectAddresses *
+new_object_addresses(void)
+{
+ ObjectAddresses *addrs;
+
+ addrs = palloc(sizeof(ObjectAddresses));
+
+ addrs->numrefs = 0;
+ addrs->maxrefs = 32;
+ addrs->refs = (ObjectAddress *)
+ palloc(addrs->maxrefs * sizeof(ObjectAddress));
+ addrs->extras = NULL; /* until/unless needed */
+
+ return addrs;
+}
+
+/*
+ * Add an entry to an ObjectAddresses array.
+ *
+ * It is convenient to specify the class by ObjectClass rather than directly
+ * by catalog OID.
+ */
+static void
+add_object_address(ObjectClass oclass, Oid objectId, int32 subId,
+ ObjectAddresses *addrs)
+{
+ ObjectAddress *item;
+
+ /*
+ * Make sure object_classes is kept up to date with the ObjectClass enum.
+ */
+ StaticAssertStmt(lengthof(object_classes) == LAST_OCLASS + 1,
+ "object_classes[] must cover all ObjectClasses");
+
+ /* enlarge array if needed */
+ if (addrs->numrefs >= addrs->maxrefs)
+ {
+ addrs->maxrefs *= 2;
+ addrs->refs = (ObjectAddress *)
+ repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
+ Assert(!addrs->extras);
+ }
+ /* record this item */
+ item = addrs->refs + addrs->numrefs;
+ item->classId = object_classes[oclass];
+ item->objectId = objectId;
+ item->objectSubId = subId;
+ addrs->numrefs++;
+}
+
+/*
+ * Add an entry to an ObjectAddresses array.
+ *
+ * As above, but specify entry exactly.
+ */
+void
+add_exact_object_address(const ObjectAddress *object,
+ ObjectAddresses *addrs)
+{
+ ObjectAddress *item;
+
+ /* enlarge array if needed */
+ if (addrs->numrefs >= addrs->maxrefs)
+ {
+ addrs->maxrefs *= 2;
+ addrs->refs = (ObjectAddress *)
+ repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
+ Assert(!addrs->extras);
+ }
+ /* record this item */
+ item = addrs->refs + addrs->numrefs;
+ *item = *object;
+ addrs->numrefs++;
+}
+
+/*
+ * Add an entry to an ObjectAddresses array.
+ *
+ * As above, but specify entry exactly and provide some "extra" data too.
+ */
+static void
+add_exact_object_address_extra(const ObjectAddress *object,
+ const ObjectAddressExtra *extra,
+ ObjectAddresses *addrs)
+{
+ ObjectAddress *item;
+ ObjectAddressExtra *itemextra;
+
+ /* allocate extra space if first time */
+ if (!addrs->extras)
+ addrs->extras = (ObjectAddressExtra *)
+ palloc(addrs->maxrefs * sizeof(ObjectAddressExtra));
+
+ /* enlarge array if needed */
+ if (addrs->numrefs >= addrs->maxrefs)
+ {
+ addrs->maxrefs *= 2;
+ addrs->refs = (ObjectAddress *)
+ repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
+ addrs->extras = (ObjectAddressExtra *)
+ repalloc(addrs->extras, addrs->maxrefs * sizeof(ObjectAddressExtra));
+ }
+ /* record this item */
+ item = addrs->refs + addrs->numrefs;
+ *item = *object;
+ itemextra = addrs->extras + addrs->numrefs;
+ *itemextra = *extra;
+ addrs->numrefs++;
+}
+
+/*
+ * Test whether an object is present in an ObjectAddresses array.
+ *
+ * We return "true" if object is a subobject of something in the array, too.
+ */
+bool
+object_address_present(const ObjectAddress *object,
+ const ObjectAddresses *addrs)
+{
+ int i;
+
+ for (i = addrs->numrefs - 1; i >= 0; i--)
+ {
+ const ObjectAddress *thisobj = addrs->refs + i;
+
+ if (object->classId == thisobj->classId &&
+ object->objectId == thisobj->objectId)
+ {
+ if (object->objectSubId == thisobj->objectSubId ||
+ thisobj->objectSubId == 0)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * As above, except that if the object is present then also OR the given
+ * flags into its associated extra data (which must exist).
+ */
+static bool
+object_address_present_add_flags(const ObjectAddress *object,
+ int flags,
+ ObjectAddresses *addrs)
+{
+ bool result = false;
+ int i;
+
+ for (i = addrs->numrefs - 1; i >= 0; i--)
+ {
+ ObjectAddress *thisobj = addrs->refs + i;
+
+ if (object->classId == thisobj->classId &&
+ object->objectId == thisobj->objectId)
+ {
+ if (object->objectSubId == thisobj->objectSubId)
+ {
+ ObjectAddressExtra *thisextra = addrs->extras + i;
+
+ thisextra->flags |= flags;
+ result = true;
+ }
+ else if (thisobj->objectSubId == 0)
+ {
+ /*
+ * We get here if we find a need to delete a column after
+ * having already decided to drop its whole table. Obviously
+ * we no longer need to drop the subobject, so report that we
+ * found the subobject in the array. But don't plaster its
+ * flags on the whole object.
+ */
+ result = true;
+ }
+ else if (object->objectSubId == 0)
+ {
+ /*
+ * We get here if we find a need to delete a whole table after
+ * having already decided to drop one of its columns. We
+ * can't report that the whole object is in the array, but we
+ * should mark the subobject with the whole object's flags.
+ *
+ * It might seem attractive to physically delete the column's
+ * array entry, or at least mark it as no longer needing
+ * separate deletion. But that could lead to, e.g., dropping
+ * the column's datatype before we drop the table, which does
+ * not seem like a good idea. This is a very rare situation
+ * in practice, so we just take the hit of doing a separate
+ * DROP COLUMN action even though we know we're gonna delete
+ * the table later.
+ *
+ * What we can do, though, is mark this as a subobject so that
+ * we don't report it separately, which is confusing because
+ * it's unpredictable whether it happens or not. But do so
+ * only if flags != 0 (flags == 0 is a read-only probe).
+ *
+ * Because there could be other subobjects of this object in
+ * the array, this case means we always have to loop through
+ * the whole array; we cannot exit early on a match.
+ */
+ ObjectAddressExtra *thisextra = addrs->extras + i;
+
+ if (flags)
+ thisextra->flags |= (flags | DEPFLAG_SUBOBJECT);
+ }
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Similar to above, except we search an ObjectAddressStack.
+ */
+static bool
+stack_address_present_add_flags(const ObjectAddress *object,
+ int flags,
+ ObjectAddressStack *stack)
+{
+ bool result = false;
+ ObjectAddressStack *stackptr;
+
+ for (stackptr = stack; stackptr; stackptr = stackptr->next)
+ {
+ const ObjectAddress *thisobj = stackptr->object;
+
+ if (object->classId == thisobj->classId &&
+ object->objectId == thisobj->objectId)
+ {
+ if (object->objectSubId == thisobj->objectSubId)
+ {
+ stackptr->flags |= flags;
+ result = true;
+ }
+ else if (thisobj->objectSubId == 0)
+ {
+ /*
+ * We're visiting a column with whole table already on stack.
+ * As in object_address_present_add_flags(), we can skip
+ * further processing of the subobject, but we don't want to
+ * propagate flags for the subobject to the whole object.
+ */
+ result = true;
+ }
+ else if (object->objectSubId == 0)
+ {
+ /*
+ * We're visiting a table with column already on stack. As in
+ * object_address_present_add_flags(), we should propagate
+ * flags for the whole object to each of its subobjects.
+ */
+ if (flags)
+ stackptr->flags |= (flags | DEPFLAG_SUBOBJECT);
+ }
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Record multiple dependencies from an ObjectAddresses array, after first
+ * removing any duplicates.
+ */
+void
+record_object_address_dependencies(const ObjectAddress *depender,
+ ObjectAddresses *referenced,
+ DependencyType behavior)
+{
+ eliminate_duplicate_dependencies(referenced);
+ recordMultipleDependencies(depender,
+ referenced->refs, referenced->numrefs,
+ behavior);
+}
+
+/*
+ * Sort the items in an ObjectAddresses array.
+ *
+ * The major sort key is OID-descending, so that newer objects will be listed
+ * first in most cases. This is primarily useful for ensuring stable outputs
+ * from regression tests; it's not recommended if the order of the objects is
+ * determined by user input, such as the order of targets in a DROP command.
+ */
+void
+sort_object_addresses(ObjectAddresses *addrs)
+{
+ if (addrs->numrefs > 1)
+ qsort((void *) addrs->refs, addrs->numrefs,
+ sizeof(ObjectAddress),
+ object_address_comparator);
+}
+
+/*
+ * Clean up when done with an ObjectAddresses array.
+ */
+void
+free_object_addresses(ObjectAddresses *addrs)
+{
+ pfree(addrs->refs);
+ if (addrs->extras)
+ pfree(addrs->extras);
+ pfree(addrs);
+}
+
+/*
+ * Determine the class of a given object identified by objectAddress.
+ *
+ * This function is essentially the reverse mapping for the object_classes[]
+ * table. We implement it as a function because the OIDs aren't consecutive.
+ */
+ObjectClass
+getObjectClass(const ObjectAddress *object)
+{
+ /* only pg_class entries can have nonzero objectSubId */
+ if (object->classId != RelationRelationId &&
+ object->objectSubId != 0)
+ elog(ERROR, "invalid non-zero objectSubId for object class %u",
+ object->classId);
+
+ switch (object->classId)
+ {
+ case RelationRelationId:
+ /* caller must check objectSubId */
+ return OCLASS_CLASS;
+
+ case ProcedureRelationId:
+ return OCLASS_PROC;
+
+ case TypeRelationId:
+ return OCLASS_TYPE;
+
+ case CastRelationId:
+ return OCLASS_CAST;
+
+ case CollationRelationId:
+ return OCLASS_COLLATION;
+
+ case ConstraintRelationId:
+ return OCLASS_CONSTRAINT;
+
+ case ConversionRelationId:
+ return OCLASS_CONVERSION;
+
+ case AttrDefaultRelationId:
+ return OCLASS_DEFAULT;
+
+ case LanguageRelationId:
+ return OCLASS_LANGUAGE;
+
+ case LargeObjectRelationId:
+ return OCLASS_LARGEOBJECT;
+
+ case OperatorRelationId:
+ return OCLASS_OPERATOR;
+
+ case OperatorClassRelationId:
+ return OCLASS_OPCLASS;
+
+ case OperatorFamilyRelationId:
+ return OCLASS_OPFAMILY;
+
+ case AccessMethodRelationId:
+ return OCLASS_AM;
+
+ case AccessMethodOperatorRelationId:
+ return OCLASS_AMOP;
+
+ case AccessMethodProcedureRelationId:
+ return OCLASS_AMPROC;
+
+ case RewriteRelationId:
+ return OCLASS_REWRITE;
+
+ case TriggerRelationId:
+ return OCLASS_TRIGGER;
+
+ case NamespaceRelationId:
+ return OCLASS_SCHEMA;
+
+ case StatisticExtRelationId:
+ return OCLASS_STATISTIC_EXT;
+
+ case TSParserRelationId:
+ return OCLASS_TSPARSER;
+
+ case TSDictionaryRelationId:
+ return OCLASS_TSDICT;
+
+ case TSTemplateRelationId:
+ return OCLASS_TSTEMPLATE;
+
+ case TSConfigRelationId:
+ return OCLASS_TSCONFIG;
+
+ case AuthIdRelationId:
+ return OCLASS_ROLE;
+
+ case DatabaseRelationId:
+ return OCLASS_DATABASE;
+
+ case TableSpaceRelationId:
+ return OCLASS_TBLSPACE;
+
+ case ForeignDataWrapperRelationId:
+ return OCLASS_FDW;
+
+ case ForeignServerRelationId:
+ return OCLASS_FOREIGN_SERVER;
+
+ case UserMappingRelationId:
+ return OCLASS_USER_MAPPING;
+
+ case DefaultAclRelationId:
+ return OCLASS_DEFACL;
+
+ case ExtensionRelationId:
+ return OCLASS_EXTENSION;
+
+ case EventTriggerRelationId:
+ return OCLASS_EVENT_TRIGGER;
+
+ case PolicyRelationId:
+ return OCLASS_POLICY;
+
+ case PublicationRelationId:
+ return OCLASS_PUBLICATION;
+
+ case PublicationRelRelationId:
+ return OCLASS_PUBLICATION_REL;
+
+ case SubscriptionRelationId:
+ return OCLASS_SUBSCRIPTION;
+
+ case TransformRelationId:
+ return OCLASS_TRANSFORM;
+ }
+
+ /* shouldn't get here */
+ elog(ERROR, "unrecognized object class: %u", object->classId);
+ return OCLASS_CLASS; /* keep compiler quiet */
+}
+
+/*
+ * delete initial ACL for extension objects
+ */
+static void
+DeleteInitPrivs(const ObjectAddress *object)
+{
+ Relation relation;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple oldtuple;
+
+ relation = table_open(InitPrivsRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_init_privs_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+ ScanKeyInit(&key[1],
+ Anum_pg_init_privs_classoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+ ScanKeyInit(&key[2],
+ Anum_pg_init_privs_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(object->objectSubId));
+
+ scan = systable_beginscan(relation, InitPrivsObjIndexId, true,
+ NULL, 3, key);
+
+ while (HeapTupleIsValid(oldtuple = systable_getnext(scan)))
+ CatalogTupleDelete(relation, &oldtuple->t_self);
+
+ systable_endscan(scan);
+
+ table_close(relation, RowExclusiveLock);
+}
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
new file mode 100644
index 0000000..b07537f
--- /dev/null
+++ b/src/backend/catalog/genbki.pl
@@ -0,0 +1,977 @@
+#!/usr/bin/perl
+#----------------------------------------------------------------------
+#
+# genbki.pl
+# Perl script that generates postgres.bki and symbol definition
+# headers from specially formatted header files and data files.
+# postgres.bki is used to initialize the postgres template database.
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/backend/catalog/genbki.pl
+#
+#----------------------------------------------------------------------
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+use FindBin;
+use lib $FindBin::RealBin;
+
+use Catalog;
+
+my $output_path = '';
+my $major_version;
+my $include_path;
+
+GetOptions(
+ 'output:s' => \$output_path,
+ 'set-version:s' => \$major_version,
+ 'include-path:s' => \$include_path) || usage();
+
+# Sanity check arguments.
+die "No input files.\n" unless @ARGV;
+die "--set-version must be specified.\n" unless $major_version;
+die "Invalid version string: $major_version\n"
+ unless $major_version =~ /^\d+$/;
+die "--include-path must be specified.\n" unless $include_path;
+
+# Make sure paths end with a slash.
+if ($output_path ne '' && substr($output_path, -1) ne '/')
+{
+ $output_path .= '/';
+}
+if (substr($include_path, -1) ne '/')
+{
+ $include_path .= '/';
+}
+
+# Read all the files into internal data structures.
+my @catnames;
+my %catalogs;
+my %catalog_data;
+my @toast_decls;
+my @index_decls;
+my %oidcounts;
+
+foreach my $header (@ARGV)
+{
+ $header =~ /(.+)\.h$/
+ or die "Input files need to be header files.\n";
+ my $datfile = "$1.dat";
+
+ my $catalog = Catalog::ParseHeader($header);
+ my $catname = $catalog->{catname};
+ my $schema = $catalog->{columns};
+
+ if (defined $catname)
+ {
+ push @catnames, $catname;
+ $catalogs{$catname} = $catalog;
+ }
+
+ # While checking for duplicated OIDs, we ignore the pg_class OID and
+ # rowtype OID of bootstrap catalogs, as those are expected to appear
+ # in the initial data for pg_class and pg_type. For regular catalogs,
+ # include these OIDs. (See also Catalog::FindAllOidsFromHeaders
+ # if you change this logic.)
+ if (!$catalog->{bootstrap})
+ {
+ $oidcounts{ $catalog->{relation_oid} }++
+ if ($catalog->{relation_oid});
+ $oidcounts{ $catalog->{rowtype_oid} }++
+ if ($catalog->{rowtype_oid});
+ }
+
+ # Not all catalogs have a data file.
+ if (-e $datfile)
+ {
+ my $data = Catalog::ParseData($datfile, $schema, 0);
+ $catalog_data{$catname} = $data;
+
+ foreach my $row (@$data)
+ {
+ # Generate entries for pg_description and pg_shdescription.
+ if (defined $row->{descr})
+ {
+ my %descr = (
+ objoid => $row->{oid},
+ classoid => $catalog->{relation_oid},
+ objsubid => 0,
+ description => $row->{descr});
+
+ if ($catalog->{shared_relation})
+ {
+ delete $descr{objsubid};
+ push @{ $catalog_data{pg_shdescription} }, \%descr;
+ }
+ else
+ {
+ push @{ $catalog_data{pg_description} }, \%descr;
+ }
+ }
+
+ # Check for duplicated OIDs while we're at it.
+ $oidcounts{ $row->{oid} }++ if defined $row->{oid};
+ }
+ }
+
+ # If the header file contained toast or index info, build BKI
+ # commands for those, which we'll output later.
+ foreach my $toast (@{ $catalog->{toasting} })
+ {
+ push @toast_decls,
+ sprintf "declare toast %s %s on %s\n",
+ $toast->{toast_oid}, $toast->{toast_index_oid},
+ $toast->{parent_table};
+ $oidcounts{ $toast->{toast_oid} }++;
+ $oidcounts{ $toast->{toast_index_oid} }++;
+ }
+ foreach my $index (@{ $catalog->{indexing} })
+ {
+ push @index_decls,
+ sprintf "declare %sindex %s %s %s\n",
+ $index->{is_unique} ? 'unique ' : '',
+ $index->{index_name}, $index->{index_oid},
+ $index->{index_decl};
+ $oidcounts{ $index->{index_oid} }++;
+ }
+}
+
+# Complain and exit if we found any duplicate OIDs.
+# While duplicate OIDs would only cause a failure if they appear in
+# the same catalog, our project policy is that manually assigned OIDs
+# should be globally unique, to avoid confusion.
+my $found = 0;
+foreach my $oid (keys %oidcounts)
+{
+ next unless $oidcounts{$oid} > 1;
+ print STDERR "Duplicate OIDs detected:\n" if !$found;
+ print STDERR "$oid\n";
+ $found++;
+}
+die "found $found duplicate OID(s) in catalog data\n" if $found;
+
+
+# Oids not specified in the input files are automatically assigned,
+# starting at FirstGenbkiObjectId, extending up to FirstBootstrapObjectId.
+my $FirstGenbkiObjectId =
+ Catalog::FindDefinedSymbol('access/transam.h', $include_path,
+ 'FirstGenbkiObjectId');
+my $FirstBootstrapObjectId =
+ Catalog::FindDefinedSymbol('access/transam.h', $include_path,
+ 'FirstBootstrapObjectId');
+my $GenbkiNextOid = $FirstGenbkiObjectId;
+
+
+# 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().)
+my $BOOTSTRAP_SUPERUSERID =
+ Catalog::FindDefinedSymbolFromData($catalog_data{pg_authid},
+ 'BOOTSTRAP_SUPERUSERID');
+my $C_COLLATION_OID =
+ Catalog::FindDefinedSymbolFromData($catalog_data{pg_collation},
+ 'C_COLLATION_OID');
+my $PG_CATALOG_NAMESPACE =
+ Catalog::FindDefinedSymbolFromData($catalog_data{pg_namespace},
+ 'PG_CATALOG_NAMESPACE');
+
+
+# Fill in pg_class.relnatts by looking at the referenced catalog's schema.
+# This is ugly but there's no better place; Catalog::AddDefaultValues
+# can't do it, for lack of easy access to the other catalog.
+foreach my $row (@{ $catalog_data{pg_class} })
+{
+ $row->{relnatts} = scalar(@{ $catalogs{ $row->{relname} }->{columns} });
+}
+
+
+# Build lookup tables.
+
+# access method OID lookup
+my %amoids;
+foreach my $row (@{ $catalog_data{pg_am} })
+{
+ $amoids{ $row->{amname} } = $row->{oid};
+}
+
+# class (relation) OID lookup (note this only covers bootstrap catalogs!)
+my %classoids;
+foreach my $row (@{ $catalog_data{pg_class} })
+{
+ $classoids{ $row->{relname} } = $row->{oid};
+}
+
+# collation OID lookup
+my %collationoids;
+foreach my $row (@{ $catalog_data{pg_collation} })
+{
+ $collationoids{ $row->{collname} } = $row->{oid};
+}
+
+# language OID lookup
+my %langoids;
+foreach my $row (@{ $catalog_data{pg_language} })
+{
+ $langoids{ $row->{lanname} } = $row->{oid};
+}
+
+# opclass OID lookup
+my %opcoids;
+foreach my $row (@{ $catalog_data{pg_opclass} })
+{
+ # There is no unique name, so we need to combine access method
+ # and opclass name.
+ my $key = sprintf "%s/%s", $row->{opcmethod}, $row->{opcname};
+ $opcoids{$key} = $row->{oid};
+}
+
+# operator OID lookup
+my %operoids;
+foreach my $row (@{ $catalog_data{pg_operator} })
+{
+ # There is no unique name, so we need to invent one that contains
+ # the relevant type names.
+ my $key = sprintf "%s(%s,%s)",
+ $row->{oprname}, $row->{oprleft}, $row->{oprright};
+ $operoids{$key} = $row->{oid};
+}
+
+# opfamily OID lookup
+my %opfoids;
+foreach my $row (@{ $catalog_data{pg_opfamily} })
+{
+ # There is no unique name, so we need to combine access method
+ # and opfamily name.
+ my $key = sprintf "%s/%s", $row->{opfmethod}, $row->{opfname};
+ $opfoids{$key} = $row->{oid};
+}
+
+# procedure OID lookup
+my %procoids;
+foreach my $row (@{ $catalog_data{pg_proc} })
+{
+ # Generate an entry under just the proname (corresponds to regproc lookup)
+ my $prokey = $row->{proname};
+ if (defined $procoids{$prokey})
+ {
+ $procoids{$prokey} = 'MULTIPLE';
+ }
+ else
+ {
+ $procoids{$prokey} = $row->{oid};
+ }
+
+ # Also generate an entry using proname(proargtypes). This is not quite
+ # identical to regprocedure lookup because we don't worry much about
+ # special SQL names for types etc; we just use the names in the source
+ # proargtypes field. These *should* be unique, but do a multiplicity
+ # check anyway.
+ $prokey .= '(' . join(',', split(/\s+/, $row->{proargtypes})) . ')';
+ if (defined $procoids{$prokey})
+ {
+ $procoids{$prokey} = 'MULTIPLE';
+ }
+ else
+ {
+ $procoids{$prokey} = $row->{oid};
+ }
+}
+
+# tablespace OID lookup
+my %tablespaceoids;
+foreach my $row (@{ $catalog_data{pg_tablespace} })
+{
+ $tablespaceoids{ $row->{spcname} } = $row->{oid};
+}
+
+# text search configuration OID lookup
+my %tsconfigoids;
+foreach my $row (@{ $catalog_data{pg_ts_config} })
+{
+ $tsconfigoids{ $row->{cfgname} } = $row->{oid};
+}
+
+# text search dictionary OID lookup
+my %tsdictoids;
+foreach my $row (@{ $catalog_data{pg_ts_dict} })
+{
+ $tsdictoids{ $row->{dictname} } = $row->{oid};
+}
+
+# text search parser OID lookup
+my %tsparseroids;
+foreach my $row (@{ $catalog_data{pg_ts_parser} })
+{
+ $tsparseroids{ $row->{prsname} } = $row->{oid};
+}
+
+# text search template OID lookup
+my %tstemplateoids;
+foreach my $row (@{ $catalog_data{pg_ts_template} })
+{
+ $tstemplateoids{ $row->{tmplname} } = $row->{oid};
+}
+
+# type lookups
+my %typeoids;
+my %types;
+foreach my $row (@{ $catalog_data{pg_type} })
+{
+ # for OID macro substitutions
+ $typeoids{ $row->{typname} } = $row->{oid};
+
+ # for pg_attribute copies of pg_type values
+ $types{ $row->{typname} } = $row;
+}
+
+# Encoding identifier lookup. This uses the same replacement machinery
+# as for OIDs, but we have to dig the values out of pg_wchar.h.
+my %encids;
+
+my $encfile = $include_path . 'mb/pg_wchar.h';
+open(my $ef, '<', $encfile) || die "$encfile: $!";
+
+# We're parsing an enum, so start with 0 and increment
+# every time we find an enum member.
+my $encid = 0;
+my $collect_encodings = 0;
+while (<$ef>)
+{
+ if (/typedef\s+enum\s+pg_enc/)
+ {
+ $collect_encodings = 1;
+ next;
+ }
+
+ last if /_PG_LAST_ENCODING_/;
+
+ if ($collect_encodings and /^\s+(PG_\w+)/)
+ {
+ $encids{$1} = $encid;
+ $encid++;
+ }
+}
+
+close $ef;
+
+# Map lookup name to the corresponding hash table.
+my %lookup_kind = (
+ pg_am => \%amoids,
+ pg_class => \%classoids,
+ pg_collation => \%collationoids,
+ pg_language => \%langoids,
+ pg_opclass => \%opcoids,
+ pg_operator => \%operoids,
+ pg_opfamily => \%opfoids,
+ pg_proc => \%procoids,
+ pg_tablespace => \%tablespaceoids,
+ pg_ts_config => \%tsconfigoids,
+ pg_ts_dict => \%tsdictoids,
+ pg_ts_parser => \%tsparseroids,
+ pg_ts_template => \%tstemplateoids,
+ pg_type => \%typeoids,
+ encoding => \%encids);
+
+
+# Open temp files
+my $tmpext = ".tmp$$";
+my $bkifile = $output_path . 'postgres.bki';
+open my $bki, '>', $bkifile . $tmpext
+ or die "can't open $bkifile$tmpext: $!";
+my $schemafile = $output_path . 'schemapg.h';
+open my $schemapg, '>', $schemafile . $tmpext
+ or die "can't open $schemafile$tmpext: $!";
+
+# Generate postgres.bki and pg_*_d.h headers.
+
+# 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;
+
+# produce output, one catalog at a time
+foreach my $catname (@catnames)
+{
+ my $catalog = $catalogs{$catname};
+
+ # Create one definition header with macro definitions for each catalog.
+ my $def_file = $output_path . $catname . '_d.h';
+ open my $def, '>', $def_file . $tmpext
+ or die "can't open $def_file$tmpext: $!";
+
+ # Opening boilerplate for pg_*_d.h
+ printf $def <<EOM, $catname, $catname, uc $catname, uc $catname;
+/*-------------------------------------------------------------------------
+ *
+ * %s_d.h
+ * Macro definitions for %s
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef %s_D_H
+#define %s_D_H
+
+EOM
+
+ # Emit OID macros for catalog's OID and rowtype OID, if wanted
+ printf $def "#define %s %s\n",
+ $catalog->{relation_oid_macro}, $catalog->{relation_oid}
+ if $catalog->{relation_oid_macro};
+ printf $def "#define %s %s\n",
+ $catalog->{rowtype_oid_macro}, $catalog->{rowtype_oid}
+ if $catalog->{rowtype_oid_macro};
+ print $def "\n";
+
+ # .bki CREATE command for this catalog
+ print $bki "create $catname $catalog->{relation_oid}"
+ . $catalog->{shared_relation}
+ . $catalog->{bootstrap}
+ . $catalog->{rowtype_oid_clause};
+
+ my $first = 1;
+
+ print $bki "\n (\n";
+ my $schema = $catalog->{columns};
+ my %attnames;
+ my $attnum = 0;
+ foreach my $column (@$schema)
+ {
+ $attnum++;
+ my $attname = $column->{name};
+ my $atttype = $column->{type};
+
+ # Build hash of column names for use later
+ $attnames{$attname} = 1;
+
+ # Emit column definitions
+ if (!$first)
+ {
+ print $bki " ,\n";
+ }
+ $first = 0;
+
+ print $bki " $attname = $atttype";
+
+ if (defined $column->{forcenotnull})
+ {
+ print $bki " FORCE NOT NULL";
+ }
+ elsif (defined $column->{forcenull})
+ {
+ print $bki " FORCE NULL";
+ }
+
+ # Emit Anum_* constants
+ printf $def "#define Anum_%s_%s %s\n", $catname, $attname, $attnum;
+ }
+ print $bki "\n )\n";
+
+ # Emit Natts_* constant
+ print $def "\n#define Natts_$catname $attnum\n\n";
+
+ # Emit client code copied from source header
+ foreach my $line (@{ $catalog->{client_code} })
+ {
+ print $def $line;
+ }
+
+ # Open it, unless it's a bootstrap catalog (create bootstrap does this
+ # automatically)
+ if (!$catalog->{bootstrap})
+ {
+ print $bki "open $catname\n";
+ }
+
+ # For pg_attribute.h, we generate data entries ourselves.
+ if ($catname eq 'pg_attribute')
+ {
+ gen_pg_attribute($schema);
+ }
+
+ # Ordinary catalog with a data file
+ foreach my $row (@{ $catalog_data{$catname} })
+ {
+ my %bki_values = %$row;
+
+ # Complain about unrecognized keys; they are presumably misspelled
+ foreach my $key (keys %bki_values)
+ {
+ next
+ if $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}
+ if (!exists($attnames{$key}));
+ }
+
+ # Perform required substitutions on fields
+ foreach my $column (@$schema)
+ {
+ my $attname = $column->{name};
+ my $atttype = $column->{type};
+
+ # Assign oid if oid column exists and no explicit assignment in row
+ if ($attname eq "oid" and not defined $bki_values{$attname})
+ {
+ $bki_values{$attname} = $GenbkiNextOid;
+ $GenbkiNextOid++;
+ }
+
+ # Substitute constant values we acquired above.
+ # (It's intentional that this can apply to parts of a field).
+ $bki_values{$attname} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g;
+ $bki_values{$attname} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g;
+
+ # Replace OID synonyms with OIDs per the appropriate lookup rule.
+ #
+ # If the column type is oidvector or _oid, we have to replace
+ # each element of the array as per the lookup rule.
+ if ($column->{lookup})
+ {
+ my $lookup = $lookup_kind{ $column->{lookup} };
+ my @lookupnames;
+ my @lookupoids;
+
+ die "unrecognized BKI_LOOKUP type " . $column->{lookup}
+ if !defined($lookup);
+
+ if ($atttype eq 'oidvector')
+ {
+ @lookupnames = split /\s+/, $bki_values{$attname};
+ @lookupoids = lookup_oids($lookup, $catname, \%bki_values,
+ @lookupnames);
+ $bki_values{$attname} = join(' ', @lookupoids);
+ }
+ elsif ($atttype eq '_oid')
+ {
+ if ($bki_values{$attname} ne '_null_')
+ {
+ $bki_values{$attname} =~ s/[{}]//g;
+ @lookupnames = split /,/, $bki_values{$attname};
+ @lookupoids =
+ lookup_oids($lookup, $catname, \%bki_values,
+ @lookupnames);
+ $bki_values{$attname} = sprintf "{%s}",
+ join(',', @lookupoids);
+ }
+ }
+ else
+ {
+ $lookupnames[0] = $bki_values{$attname};
+ @lookupoids = lookup_oids($lookup, $catname, \%bki_values,
+ @lookupnames);
+ $bki_values{$attname} = $lookupoids[0];
+ }
+ }
+ }
+
+ # Special hack to generate OID symbols for pg_type entries
+ # that lack one.
+ if ($catname eq 'pg_type' and !exists $bki_values{oid_symbol})
+ {
+ my $symbol = form_pg_type_symbol($bki_values{typname});
+ $bki_values{oid_symbol} = $symbol
+ if defined $symbol;
+ }
+
+ # Write to postgres.bki
+ print_bki_insert(\%bki_values, $schema);
+
+ # Emit OID symbol
+ if (defined $bki_values{oid_symbol})
+ {
+ printf $def "#define %s %s\n",
+ $bki_values{oid_symbol}, $bki_values{oid};
+ }
+ }
+
+ print $bki "close $catname\n";
+ printf $def "\n#endif\t\t\t\t\t\t\t/* %s_D_H */\n", uc $catname;
+
+ # Close and rename definition header
+ close $def;
+ Catalog::RenameTempFile($def_file, $tmpext);
+}
+
+# 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 (@toast_decls)
+{
+ print $bki $declaration;
+}
+
+foreach my $declaration (@index_decls)
+{
+ print $bki $declaration;
+}
+
+# last command in the BKI file: build the indexes declared above
+print $bki "build indices\n";
+
+# check that we didn't overrun available OIDs
+die
+ "genbki OID counter reached $GenbkiNextOid, overrunning FirstBootstrapObjectId\n"
+ if $GenbkiNextOid > $FirstBootstrapObjectId;
+
+
+# Now generate schemapg.h
+
+# Opening boilerplate for schemapg.h
+print $schemapg <<EOM;
+/*-------------------------------------------------------------------------
+ *
+ * schemapg.h
+ * Schema_pg_xxx macros for use by relcache.c
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SCHEMAPG_H
+#define SCHEMAPG_H
+EOM
+
+# Emit schemapg declarations
+foreach my $table_name (@tables_needing_macros)
+{
+ print $schemapg "\n#define Schema_$table_name \\\n";
+ print $schemapg join ", \\\n", @{ $schemapg_entries{$table_name} };
+ print $schemapg "\n";
+}
+
+# Closing boilerplate for schemapg.h
+print $schemapg "\n#endif\t\t\t\t\t\t\t/* SCHEMAPG_H */\n";
+
+# We're done emitting data
+close $bki;
+close $schemapg;
+
+# Finally, rename the completed files into place.
+Catalog::RenameTempFile($bkifile, $tmpext);
+Catalog::RenameTempFile($schemafile, $tmpext);
+
+exit 0;
+
+#################### Subroutines ########################
+
+
+# For each catalog marked as needing a schema macro, generate the
+# per-user-attribute data to be incorporated into schemapg.h. Also, for
+# bootstrap catalogs, emit pg_attribute entries into the .bki file
+# for both user and system attributes.
+sub gen_pg_attribute
+{
+ my $schema = shift;
+
+ my @attnames;
+ foreach my $column (@$schema)
+ {
+ push @attnames, $column->{name};
+ }
+
+ foreach my $table_name (@catnames)
+ {
+ my $table = $catalogs{$table_name};
+
+ # Currently, all bootstrap catalogs also need schemapg.h
+ # entries, so skip if it isn't to be in schemapg.h.
+ next if !$table->{schema_macro};
+
+ $schemapg_entries{$table_name} = [];
+ push @tables_needing_macros, $table_name;
+
+ # Generate entries for user attributes.
+ my $attnum = 0;
+ my $priornotnull = 1;
+ foreach my $attr (@{ $table->{columns} })
+ {
+ $attnum++;
+ my %row;
+ $row{attnum} = $attnum;
+ $row{attrelid} = $table->{relation_oid};
+
+ morph_row_for_pgattr(\%row, $schema, $attr, $priornotnull);
+ $priornotnull &= ($row{attnotnull} eq 't');
+
+ # If it's bootstrapped, put an entry in postgres.bki.
+ print_bki_insert(\%row, $schema) if $table->{bootstrap};
+
+ # Store schemapg entries for later.
+ morph_row_for_schemapg(\%row, $schema);
+ push @{ $schemapg_entries{$table_name} },
+ sprintf "{ %s }",
+ join(', ', grep { defined $_ } @row{@attnames});
+ }
+
+ # Generate entries for system attributes.
+ # We only need postgres.bki entries, not schemapg.h entries.
+ if ($table->{bootstrap})
+ {
+ $attnum = 0;
+ my @SYS_ATTRS = (
+ { name => 'ctid', type => 'tid' },
+ { name => 'xmin', type => 'xid' },
+ { name => 'cmin', type => 'cid' },
+ { name => 'xmax', type => 'xid' },
+ { name => 'cmax', type => 'cid' },
+ { name => 'tableoid', type => 'oid' });
+ foreach my $attr (@SYS_ATTRS)
+ {
+ $attnum--;
+ my %row;
+ $row{attnum} = $attnum;
+ $row{attrelid} = $table->{relation_oid};
+ $row{attstattarget} = '0';
+
+ morph_row_for_pgattr(\%row, $schema, $attr, 1);
+ print_bki_insert(\%row, $schema);
+ }
+ }
+ }
+ return;
+}
+
+# Given $pgattr_schema (the pg_attribute schema for a catalog sufficient for
+# AddDefaultValues), $attr (the description of a catalog row), and
+# $priornotnull (whether all prior attributes in this catalog are not null),
+# modify the $row hashref for print_bki_insert. This includes setting data
+# from the corresponding pg_type element and filling in any default values.
+# Any value not handled here must be supplied by caller.
+sub morph_row_for_pgattr
+{
+ my ($row, $pgattr_schema, $attr, $priornotnull) = @_;
+ my $attname = $attr->{name};
+ my $atttype = $attr->{type};
+
+ $row->{attname} = $attname;
+
+ # Copy the type data from pg_type, and add some type-dependent items
+ my $type = $types{$atttype};
+
+ $row->{atttypid} = $type->{oid};
+ $row->{attlen} = $type->{typlen};
+ $row->{attbyval} = $type->{typbyval};
+ $row->{attstorage} = $type->{typstorage};
+ $row->{attalign} = $type->{typalign};
+
+ # set attndims if it's an array type
+ $row->{attndims} = $type->{typcategory} eq 'A' ? '1' : '0';
+
+ # collation-aware catalog columns must use C collation
+ $row->{attcollation} =
+ $type->{typcollation} ne '0' ? $C_COLLATION_OID : 0;
+
+ if (defined $attr->{forcenotnull})
+ {
+ $row->{attnotnull} = 't';
+ }
+ elsif (defined $attr->{forcenull})
+ {
+ $row->{attnotnull} = 'f';
+ }
+ elsif ($priornotnull)
+ {
+
+ # attnotnull will automatically be set if the type is
+ # fixed-width and prior columns are all NOT NULL ---
+ # compare DefineAttr in bootstrap.c. oidvector and
+ # int2vector are also treated as not-nullable.
+ $row->{attnotnull} =
+ $type->{typname} eq 'oidvector' ? 't'
+ : $type->{typname} eq 'int2vector' ? 't'
+ : $type->{typlen} eq 'NAMEDATALEN' ? 't'
+ : $type->{typlen} > 0 ? 't'
+ : 'f';
+ }
+ else
+ {
+ $row->{attnotnull} = 'f';
+ }
+
+ Catalog::AddDefaultValues($row, $pgattr_schema, 'pg_attribute');
+ return;
+}
+
+# Write an entry to postgres.bki.
+sub print_bki_insert
+{
+ my $row = shift;
+ my $schema = shift;
+
+ my @bki_values;
+
+ foreach my $column (@$schema)
+ {
+ my $attname = $column->{name};
+ my $atttype = $column->{type};
+ my $bki_value = $row->{$attname};
+
+ # Fold backslash-zero to empty string if it's the entire string,
+ # since that represents a NUL char in C code.
+ $bki_value = '' if $bki_value eq '\0';
+
+ # Handle single quotes by doubling them, and double quotes by
+ # converting them to octal escapes, because that's what the
+ # bootstrap scanner requires. We do not process backslashes
+ # specially; this allows escape-string-style backslash escapes
+ # to be used in catalog data.
+ $bki_value =~ s/'/''/g;
+ $bki_value =~ s/"/\\042/g;
+
+ # Quote value if needed. We need not quote values that satisfy
+ # the "id" pattern in bootscanner.l, currently "[-A-Za-z0-9_]+".
+ $bki_value = sprintf(qq'"%s"', $bki_value)
+ if length($bki_value) == 0
+ or $bki_value =~ /[^-A-Za-z0-9_]/;
+
+ push @bki_values, $bki_value;
+ }
+ printf $bki "insert ( %s )\n", join(' ', @bki_values);
+ return;
+}
+
+# Given a row reference, modify it so that it becomes a valid entry for
+# a catalog schema declaration in schemapg.h.
+#
+# The field values of a Schema_pg_xxx declaration are similar, but not
+# quite identical, to the corresponding values in postgres.bki.
+sub morph_row_for_schemapg
+{
+ my $row = shift;
+ my $pgattr_schema = shift;
+
+ foreach my $column (@$pgattr_schema)
+ {
+ my $attname = $column->{name};
+ my $atttype = $column->{type};
+
+ # Some data types have special formatting rules.
+ if ($atttype eq 'name')
+ {
+ # add {" ... "} quoting
+ $row->{$attname} = sprintf(qq'{"%s"}', $row->{$attname});
+ }
+ elsif ($atttype eq 'char')
+ {
+ # Add single quotes
+ $row->{$attname} = sprintf("'%s'", $row->{$attname});
+ }
+
+ # Expand booleans from 'f'/'t' to 'false'/'true'.
+ # Some values might be other macros (eg FLOAT8PASSBYVAL),
+ # don't change.
+ elsif ($atttype eq 'bool')
+ {
+ $row->{$attname} = 'true' if $row->{$attname} eq 't';
+ $row->{$attname} = 'false' if $row->{$attname} eq 'f';
+ }
+
+ # We don't emit initializers for the variable length fields at all.
+ # Only the fixed-size portions of the descriptors are ever used.
+ delete $row->{$attname} if $column->{is_varlen};
+ }
+ return;
+}
+
+# Perform OID lookups on an array of OID names.
+# If we don't have a unique value to substitute, warn and
+# leave the entry unchanged.
+# (A warning seems sufficient because the bootstrap backend will reject
+# non-numeric values anyway. So we might as well detect multiple problems
+# within this genbki.pl run.)
+sub lookup_oids
+{
+ my ($lookup, $catname, $bki_values, @lookupnames) = @_;
+
+ my @lookupoids;
+ foreach my $lookupname (@lookupnames)
+ {
+ my $lookupoid = $lookup->{$lookupname};
+ if (defined($lookupoid) and $lookupoid ne 'MULTIPLE')
+ {
+ push @lookupoids, $lookupoid;
+ }
+ else
+ {
+ push @lookupoids, $lookupname;
+ warn sprintf
+ "unresolved OID reference \"%s\" in %s.dat line %s\n",
+ $lookupname, $catname, $bki_values->{line_number}
+ if $lookupname ne '-' and $lookupname ne '0';
+ }
+ }
+ return @lookupoids;
+}
+
+# Determine canonical pg_type OID #define symbol from the type name.
+sub form_pg_type_symbol
+{
+ my $typename = shift;
+
+ # Skip for rowtypes of bootstrap catalogs, since they have their
+ # own naming convention defined elsewhere.
+ return
+ if $typename eq 'pg_type'
+ or $typename eq 'pg_proc'
+ or $typename eq 'pg_attribute'
+ or $typename eq 'pg_class';
+
+ # Transform like so:
+ # foo_bar -> FOO_BAROID
+ # _foo_bar -> FOO_BARARRAYOID
+ $typename =~ /(_)?(.+)/;
+ my $arraystr = $1 ? 'ARRAY' : '';
+ my $name = uc $2;
+ return $name . $arraystr . 'OID';
+}
+
+sub usage
+{
+ die <<EOM;
+Usage: perl -I [directory of Catalog.pm] genbki.pl [--output/-o <path>] [--include-path/-i <path>] header...
+
+Options:
+ --output Output directory (default '.')
+ --set-version PostgreSQL version number for initdb cross-check
+ --include-path Include path in source tree
+
+genbki.pl generates postgres.bki and symbol definition
+headers from specially formatted header files and .dat
+files. postgres.bki is used to initialize the
+postgres template database.
+
+Report bugs to <pgsql-bugs\@lists.postgresql.org>.
+EOM
+}
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
new file mode 100644
index 0000000..a42070f
--- /dev/null
+++ b/src/backend/catalog/heap.c
@@ -0,0 +1,3826 @@
+/*-------------------------------------------------------------------------
+ *
+ * heap.c
+ * code to create and destroy POSTGRES heap relations
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/heap.c
+ *
+ *
+ * INTERFACE ROUTINES
+ * heap_create() - Create an uncataloged heap relation
+ * heap_create_with_catalog() - Create a cataloged relation
+ * heap_drop_with_catalog() - Removes named relation from catalogs
+ *
+ * NOTES
+ * this code taken from access/heap/create.c, which contains
+ * the old heap_create_with_catalog, amcreate, and amdestroy.
+ * those routines will soon call these routines using the function
+ * manager,
+ * just like the poorly named "NewXXX" routines do. The
+ * "New" routines are all going to die soon, once and for all!
+ * -cim 1/13/91
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/multixact.h"
+#include "access/relation.h"
+#include "access/sysattr.h"
+#include "access/table.h"
+#include "access/tableam.h"
+#include "access/transam.h"
+#include "access/xact.h"
+#include "access/xlog.h"
+#include "catalog/binary_upgrade.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/heap.h"
+#include "catalog/index.h"
+#include "catalog/objectaccess.h"
+#include "catalog/partition.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_attrdef.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_constraint.h"
+#include "catalog/pg_foreign_table.h"
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_partitioned_table.h"
+#include "catalog/pg_statistic.h"
+#include "catalog/pg_subscription_rel.h"
+#include "catalog/pg_tablespace.h"
+#include "catalog/pg_type.h"
+#include "catalog/storage.h"
+#include "catalog/storage_xlog.h"
+#include "commands/tablecmds.h"
+#include "commands/typecmds.h"
+#include "executor/executor.h"
+#include "miscadmin.h"
+#include "nodes/nodeFuncs.h"
+#include "optimizer/optimizer.h"
+#include "parser/parse_coerce.h"
+#include "parser/parse_collate.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_relation.h"
+#include "parser/parsetree.h"
+#include "partitioning/partdesc.h"
+#include "storage/lmgr.h"
+#include "storage/predicate.h"
+#include "storage/smgr.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/datum.h"
+#include "utils/fmgroids.h"
+#include "utils/inval.h"
+#include "utils/lsyscache.h"
+#include "utils/partcache.h"
+#include "utils/ruleutils.h"
+#include "utils/snapmgr.h"
+#include "utils/syscache.h"
+
+
+/* Potentially set by pg_upgrade_support functions */
+Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid;
+Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid;
+
+static void AddNewRelationTuple(Relation pg_class_desc,
+ Relation new_rel_desc,
+ Oid new_rel_oid,
+ Oid new_type_oid,
+ Oid reloftype,
+ Oid relowner,
+ char relkind,
+ TransactionId relfrozenxid,
+ TransactionId relminmxid,
+ Datum relacl,
+ Datum reloptions);
+static ObjectAddress AddNewRelationType(const char *typeName,
+ Oid typeNamespace,
+ Oid new_rel_oid,
+ char new_rel_kind,
+ Oid ownerid,
+ Oid new_row_type,
+ Oid new_array_type);
+static void RelationRemoveInheritance(Oid relid);
+static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr,
+ bool is_validated, bool is_local, int inhcount,
+ bool is_no_inherit, bool is_internal);
+static void StoreConstraints(Relation rel, List *cooked_constraints,
+ bool is_internal);
+static bool MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
+ bool allow_merge, bool is_local,
+ bool is_initially_valid,
+ bool is_no_inherit);
+static void SetRelationNumChecks(Relation rel, int numchecks);
+static Node *cookConstraint(ParseState *pstate,
+ Node *raw_constraint,
+ char *relname);
+
+
+/* ----------------------------------------------------------------
+ * XXX UGLY HARD CODED BADNESS FOLLOWS XXX
+ *
+ * these should all be moved to someplace in the lib/catalog
+ * module, if not obliterated first.
+ * ----------------------------------------------------------------
+ */
+
+
+/*
+ * Note:
+ * Should the system special case these attributes in the future?
+ * Advantage: consume much less space in the ATTRIBUTE relation.
+ * Disadvantage: special cases will be all over the place.
+ */
+
+/*
+ * The initializers below do not include trailing variable length fields,
+ * but that's OK - we're never going to reference anything beyond the
+ * fixed-size portion of the structure anyway.
+ */
+
+static const FormData_pg_attribute a1 = {
+ .attname = {"ctid"},
+ .atttypid = TIDOID,
+ .attlen = sizeof(ItemPointerData),
+ .attnum = SelfItemPointerAttributeNumber,
+ .attcacheoff = -1,
+ .atttypmod = -1,
+ .attbyval = false,
+ .attstorage = TYPSTORAGE_PLAIN,
+ .attalign = TYPALIGN_SHORT,
+ .attnotnull = true,
+ .attislocal = true,
+};
+
+static const FormData_pg_attribute a2 = {
+ .attname = {"xmin"},
+ .atttypid = XIDOID,
+ .attlen = sizeof(TransactionId),
+ .attnum = MinTransactionIdAttributeNumber,
+ .attcacheoff = -1,
+ .atttypmod = -1,
+ .attbyval = true,
+ .attstorage = TYPSTORAGE_PLAIN,
+ .attalign = TYPALIGN_INT,
+ .attnotnull = true,
+ .attislocal = true,
+};
+
+static const FormData_pg_attribute a3 = {
+ .attname = {"cmin"},
+ .atttypid = CIDOID,
+ .attlen = sizeof(CommandId),
+ .attnum = MinCommandIdAttributeNumber,
+ .attcacheoff = -1,
+ .atttypmod = -1,
+ .attbyval = true,
+ .attstorage = TYPSTORAGE_PLAIN,
+ .attalign = TYPALIGN_INT,
+ .attnotnull = true,
+ .attislocal = true,
+};
+
+static const FormData_pg_attribute a4 = {
+ .attname = {"xmax"},
+ .atttypid = XIDOID,
+ .attlen = sizeof(TransactionId),
+ .attnum = MaxTransactionIdAttributeNumber,
+ .attcacheoff = -1,
+ .atttypmod = -1,
+ .attbyval = true,
+ .attstorage = TYPSTORAGE_PLAIN,
+ .attalign = TYPALIGN_INT,
+ .attnotnull = true,
+ .attislocal = true,
+};
+
+static const FormData_pg_attribute a5 = {
+ .attname = {"cmax"},
+ .atttypid = CIDOID,
+ .attlen = sizeof(CommandId),
+ .attnum = MaxCommandIdAttributeNumber,
+ .attcacheoff = -1,
+ .atttypmod = -1,
+ .attbyval = true,
+ .attstorage = TYPSTORAGE_PLAIN,
+ .attalign = TYPALIGN_INT,
+ .attnotnull = true,
+ .attislocal = true,
+};
+
+/*
+ * We decided to call this attribute "tableoid" rather than say
+ * "classoid" on the basis that in the future there may be more than one
+ * table of a particular class/type. In any case table is still the word
+ * used in SQL.
+ */
+static const FormData_pg_attribute a6 = {
+ .attname = {"tableoid"},
+ .atttypid = OIDOID,
+ .attlen = sizeof(Oid),
+ .attnum = TableOidAttributeNumber,
+ .attcacheoff = -1,
+ .atttypmod = -1,
+ .attbyval = true,
+ .attstorage = TYPSTORAGE_PLAIN,
+ .attalign = TYPALIGN_INT,
+ .attnotnull = true,
+ .attislocal = true,
+};
+
+static const FormData_pg_attribute *SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6};
+
+/*
+ * This function returns a Form_pg_attribute pointer for a system attribute.
+ * Note that we elog if the presented attno is invalid, which would only
+ * happen if there's a problem upstream.
+ */
+const FormData_pg_attribute *
+SystemAttributeDefinition(AttrNumber attno)
+{
+ if (attno >= 0 || attno < -(int) lengthof(SysAtt))
+ elog(ERROR, "invalid system attribute number %d", attno);
+ return SysAtt[-attno - 1];
+}
+
+/*
+ * If the given name is a system attribute name, return a Form_pg_attribute
+ * pointer for a prototype definition. If not, return NULL.
+ */
+const FormData_pg_attribute *
+SystemAttributeByName(const char *attname)
+{
+ int j;
+
+ for (j = 0; j < (int) lengthof(SysAtt); j++)
+ {
+ const FormData_pg_attribute *att = SysAtt[j];
+
+ if (strcmp(NameStr(att->attname), attname) == 0)
+ return att;
+ }
+
+ return NULL;
+}
+
+
+/* ----------------------------------------------------------------
+ * XXX END OF UGLY HARD CODED BADNESS XXX
+ * ---------------------------------------------------------------- */
+
+
+/* ----------------------------------------------------------------
+ * heap_create - Create an uncataloged heap relation
+ *
+ * Note API change: the caller must now always provide the OID
+ * to use for the relation. The relfilenode may (and, normally,
+ * should) be left unspecified.
+ *
+ * rel->rd_rel is initialized by RelationBuildLocalRelation,
+ * and is mostly zeroes at return.
+ * ----------------------------------------------------------------
+ */
+Relation
+heap_create(const char *relname,
+ Oid relnamespace,
+ Oid reltablespace,
+ Oid relid,
+ Oid relfilenode,
+ Oid accessmtd,
+ TupleDesc tupDesc,
+ char relkind,
+ char relpersistence,
+ bool shared_relation,
+ bool mapped_relation,
+ bool allow_system_table_mods,
+ TransactionId *relfrozenxid,
+ MultiXactId *relminmxid)
+{
+ bool create_storage;
+ Relation rel;
+
+ /* The caller must have provided an OID for the relation. */
+ Assert(OidIsValid(relid));
+
+ /*
+ * Don't allow creating relations in pg_catalog directly, even though it
+ * is allowed to move user defined relations there. Semantics with search
+ * paths including pg_catalog are too confusing for now.
+ *
+ * But allow creating indexes on relations in pg_catalog even if
+ * allow_system_table_mods = off, upper layers already guarantee it's on a
+ * user defined relation, not a system one.
+ */
+ if (!allow_system_table_mods &&
+ ((IsCatalogNamespace(relnamespace) && relkind != RELKIND_INDEX) ||
+ IsToastNamespace(relnamespace)) &&
+ IsNormalProcessingMode())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to create \"%s.%s\"",
+ get_namespace_name(relnamespace), relname),
+ errdetail("System catalog modifications are currently disallowed.")));
+
+ *relfrozenxid = InvalidTransactionId;
+ *relminmxid = InvalidMultiXactId;
+
+ /* Handle reltablespace for specific relkinds. */
+ switch (relkind)
+ {
+ case RELKIND_VIEW:
+ case RELKIND_COMPOSITE_TYPE:
+ case RELKIND_FOREIGN_TABLE:
+
+ /*
+ * Force reltablespace to zero if the relation has no physical
+ * storage. This is mainly just for cleanliness' sake.
+ *
+ * Partitioned tables and indexes don't have physical storage
+ * either, but we want to keep their tablespace settings so that
+ * their children can inherit it.
+ */
+ reltablespace = InvalidOid;
+ break;
+
+ case RELKIND_SEQUENCE:
+
+ /*
+ * Force reltablespace to zero for sequences, since we don't
+ * support moving them around into different tablespaces.
+ */
+ reltablespace = InvalidOid;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Decide whether to create storage. If caller passed a valid relfilenode,
+ * storage is already created, so don't do it here. Also don't create it
+ * for relkinds without physical storage.
+ */
+ if (!RELKIND_HAS_STORAGE(relkind) || OidIsValid(relfilenode))
+ create_storage = false;
+ else
+ {
+ create_storage = true;
+ relfilenode = relid;
+ }
+
+ /*
+ * Never allow a pg_class entry to explicitly specify the database's
+ * default tablespace in reltablespace; force it to zero instead. This
+ * ensures that if the database is cloned with a different default
+ * tablespace, the pg_class entry will still match where CREATE DATABASE
+ * will put the physically copied relation.
+ *
+ * Yes, this is a bit of a hack.
+ */
+ if (reltablespace == MyDatabaseTableSpace)
+ reltablespace = InvalidOid;
+
+ /*
+ * build the relcache entry.
+ */
+ rel = RelationBuildLocalRelation(relname,
+ relnamespace,
+ tupDesc,
+ relid,
+ accessmtd,
+ relfilenode,
+ reltablespace,
+ shared_relation,
+ mapped_relation,
+ relpersistence,
+ relkind);
+
+ /*
+ * Have the storage manager create the relation's disk file, if needed.
+ *
+ * For relations the callback creates both the main and the init fork, for
+ * indexes only the main fork is created. The other forks will be created
+ * on demand.
+ */
+ if (create_storage)
+ {
+ RelationOpenSmgr(rel);
+
+ switch (rel->rd_rel->relkind)
+ {
+ case RELKIND_VIEW:
+ case RELKIND_COMPOSITE_TYPE:
+ case RELKIND_FOREIGN_TABLE:
+ case RELKIND_PARTITIONED_TABLE:
+ case RELKIND_PARTITIONED_INDEX:
+ Assert(false);
+ break;
+
+ case RELKIND_INDEX:
+ case RELKIND_SEQUENCE:
+ RelationCreateStorage(rel->rd_node, relpersistence);
+ break;
+
+ case RELKIND_RELATION:
+ case RELKIND_TOASTVALUE:
+ case RELKIND_MATVIEW:
+ table_relation_set_new_filenode(rel, &rel->rd_node,
+ relpersistence,
+ relfrozenxid, relminmxid);
+ break;
+ }
+ }
+
+ /*
+ * If a tablespace is specified, removal of that tablespace is normally
+ * protected by the existence of a physical file; but for relations with
+ * no files, add a pg_shdepend entry to account for that.
+ */
+ if (!create_storage && reltablespace != InvalidOid)
+ recordDependencyOnTablespace(RelationRelationId, relid,
+ reltablespace);
+
+ return rel;
+}
+
+/* ----------------------------------------------------------------
+ * heap_create_with_catalog - Create a cataloged relation
+ *
+ * this is done in multiple steps:
+ *
+ * 1) CheckAttributeNamesTypes() is used to make certain the tuple
+ * descriptor contains a valid set of attribute names and types
+ *
+ * 2) pg_class is opened and get_relname_relid()
+ * performs a scan to ensure that no relation with the
+ * same name already exists.
+ *
+ * 3) heap_create() is called to create the new relation on disk.
+ *
+ * 4) TypeCreate() is called to define a new type corresponding
+ * to the new relation.
+ *
+ * 5) AddNewRelationTuple() is called to register the
+ * relation in pg_class.
+ *
+ * 6) AddNewAttributeTuples() is called to register the
+ * new relation's schema in pg_attribute.
+ *
+ * 7) StoreConstraints is called () - vadim 08/22/97
+ *
+ * 8) the relations are closed and the new relation's oid
+ * is returned.
+ *
+ * ----------------------------------------------------------------
+ */
+
+/* --------------------------------
+ * CheckAttributeNamesTypes
+ *
+ * this is used to make certain the tuple descriptor contains a
+ * valid set of attribute names and datatypes. a problem simply
+ * generates ereport(ERROR) which aborts the current transaction.
+ *
+ * relkind is the relkind of the relation to be created.
+ * flags controls which datatypes are allowed, cf CheckAttributeType.
+ * --------------------------------
+ */
+void
+CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
+ int flags)
+{
+ int i;
+ int j;
+ int natts = tupdesc->natts;
+
+ /* Sanity check on column count */
+ if (natts < 0 || natts > MaxHeapAttributeNumber)
+ ereport(ERROR,
+ (errcode(ERRCODE_TOO_MANY_COLUMNS),
+ errmsg("tables can have at most %d columns",
+ MaxHeapAttributeNumber)));
+
+ /*
+ * first check for collision with system attribute names
+ *
+ * Skip this for a view or type relation, since those don't have system
+ * attributes.
+ */
+ if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
+ {
+ for (i = 0; i < natts; i++)
+ {
+ Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
+
+ if (SystemAttributeByName(NameStr(attr->attname)) != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_COLUMN),
+ errmsg("column name \"%s\" conflicts with a system column name",
+ NameStr(attr->attname))));
+ }
+ }
+
+ /*
+ * next check for repeated attribute names
+ */
+ for (i = 1; i < natts; i++)
+ {
+ for (j = 0; j < i; j++)
+ {
+ if (strcmp(NameStr(TupleDescAttr(tupdesc, j)->attname),
+ NameStr(TupleDescAttr(tupdesc, i)->attname)) == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_COLUMN),
+ errmsg("column name \"%s\" specified more than once",
+ NameStr(TupleDescAttr(tupdesc, j)->attname))));
+ }
+ }
+
+ /*
+ * next check the attribute types
+ */
+ for (i = 0; i < natts; i++)
+ {
+ CheckAttributeType(NameStr(TupleDescAttr(tupdesc, i)->attname),
+ TupleDescAttr(tupdesc, i)->atttypid,
+ TupleDescAttr(tupdesc, i)->attcollation,
+ NIL, /* assume we're creating a new rowtype */
+ flags);
+ }
+}
+
+/* --------------------------------
+ * CheckAttributeType
+ *
+ * Verify that the proposed datatype of an attribute is legal.
+ * This is needed mainly because there are types (and pseudo-types)
+ * in the catalogs that we do not support as elements of real tuples.
+ * We also check some other properties required of a table column.
+ *
+ * If the attribute is being proposed for addition to an existing table or
+ * composite type, pass a one-element list of the rowtype OID as
+ * containing_rowtypes. When checking a to-be-created rowtype, it's
+ * sufficient to pass NIL, because there could not be any recursive reference
+ * to a not-yet-existing rowtype.
+ *
+ * flags is a bitmask controlling which datatypes we allow. For the most
+ * part, pseudo-types are disallowed as attribute types, but there are some
+ * exceptions: ANYARRAYOID, RECORDOID, and RECORDARRAYOID can be allowed
+ * in some cases. (This works because values of those type classes are
+ * self-identifying to some extent. However, RECORDOID and RECORDARRAYOID
+ * are reliably identifiable only within a session, since the identity info
+ * may use a typmod that is only locally assigned. The caller is expected
+ * to know whether these cases are safe.)
+ *
+ * flags can also control the phrasing of the error messages. If
+ * CHKATYPE_IS_PARTKEY is specified, "attname" should be a partition key
+ * column number as text, not a real column name.
+ * --------------------------------
+ */
+void
+CheckAttributeType(const char *attname,
+ Oid atttypid, Oid attcollation,
+ List *containing_rowtypes,
+ int flags)
+{
+ char att_typtype = get_typtype(atttypid);
+ Oid att_typelem;
+
+ if (att_typtype == TYPTYPE_PSEUDO)
+ {
+ /*
+ * We disallow pseudo-type columns, with the exception of ANYARRAY,
+ * RECORD, and RECORD[] when the caller says that those are OK.
+ *
+ * We don't need to worry about recursive containment for RECORD and
+ * RECORD[] because (a) no named composite type should be allowed to
+ * contain those, and (b) two "anonymous" record types couldn't be
+ * considered to be the same type, so infinite recursion isn't
+ * possible.
+ */
+ if (!((atttypid == ANYARRAYOID && (flags & CHKATYPE_ANYARRAY)) ||
+ (atttypid == RECORDOID && (flags & CHKATYPE_ANYRECORD)) ||
+ (atttypid == RECORDARRAYOID && (flags & CHKATYPE_ANYRECORD))))
+ {
+ if (flags & CHKATYPE_IS_PARTKEY)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ /* translator: first %s is an integer not a name */
+ errmsg("partition key column %s has pseudo-type %s",
+ attname, format_type_be(atttypid))));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("column \"%s\" has pseudo-type %s",
+ attname, format_type_be(atttypid))));
+ }
+ }
+ else if (att_typtype == TYPTYPE_DOMAIN)
+ {
+ /*
+ * If it's a domain, recurse to check its base type.
+ */
+ CheckAttributeType(attname, getBaseType(atttypid), attcollation,
+ containing_rowtypes,
+ flags);
+ }
+ else if (att_typtype == TYPTYPE_COMPOSITE)
+ {
+ /*
+ * For a composite type, recurse into its attributes.
+ */
+ Relation relation;
+ TupleDesc tupdesc;
+ int i;
+
+ /*
+ * Check for self-containment. Eventually we might be able to allow
+ * this (just return without complaint, if so) but it's not clear how
+ * many other places would require anti-recursion defenses before it
+ * would be safe to allow tables to contain their own rowtype.
+ */
+ if (list_member_oid(containing_rowtypes, atttypid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("composite type %s cannot be made a member of itself",
+ format_type_be(atttypid))));
+
+ containing_rowtypes = lappend_oid(containing_rowtypes, atttypid);
+
+ relation = relation_open(get_typ_typrelid(atttypid), AccessShareLock);
+
+ tupdesc = RelationGetDescr(relation);
+
+ for (i = 0; i < tupdesc->natts; i++)
+ {
+ Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
+
+ if (attr->attisdropped)
+ continue;
+ CheckAttributeType(NameStr(attr->attname),
+ attr->atttypid, attr->attcollation,
+ containing_rowtypes,
+ flags & ~CHKATYPE_IS_PARTKEY);
+ }
+
+ relation_close(relation, AccessShareLock);
+
+ containing_rowtypes = list_delete_last(containing_rowtypes);
+ }
+ else if (att_typtype == TYPTYPE_RANGE)
+ {
+ /*
+ * If it's a range, recurse to check its subtype.
+ */
+ CheckAttributeType(attname, get_range_subtype(atttypid),
+ get_range_collation(atttypid),
+ containing_rowtypes,
+ flags);
+ }
+ else if (OidIsValid((att_typelem = get_element_type(atttypid))))
+ {
+ /*
+ * Must recurse into array types, too, in case they are composite.
+ */
+ CheckAttributeType(attname, att_typelem, attcollation,
+ containing_rowtypes,
+ flags);
+ }
+
+ /*
+ * This might not be strictly invalid per SQL standard, but it is pretty
+ * useless, and it cannot be dumped, so we must disallow it.
+ */
+ if (!OidIsValid(attcollation) && type_is_collatable(atttypid))
+ {
+ if (flags & CHKATYPE_IS_PARTKEY)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ /* translator: first %s is an integer not a name */
+ errmsg("no collation was derived for partition key column %s with collatable type %s",
+ attname, format_type_be(atttypid)),
+ errhint("Use the COLLATE clause to set the collation explicitly.")));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("no collation was derived for column \"%s\" with collatable type %s",
+ attname, format_type_be(atttypid)),
+ errhint("Use the COLLATE clause to set the collation explicitly.")));
+ }
+}
+
+/*
+ * InsertPgAttributeTuple
+ * Construct and insert a new tuple in pg_attribute.
+ *
+ * Caller has already opened and locked pg_attribute. new_attribute is the
+ * attribute to insert. attcacheoff is always initialized to -1, attacl and
+ * attoptions are always initialized to NULL.
+ *
+ * indstate is the index state for CatalogTupleInsertWithInfo. It can be
+ * passed as NULL, in which case we'll fetch the necessary info. (Don't do
+ * this when inserting multiple attributes, because it's a tad more
+ * expensive.)
+ */
+void
+InsertPgAttributeTuple(Relation pg_attribute_rel,
+ Form_pg_attribute new_attribute,
+ Datum attoptions,
+ CatalogIndexState indstate)
+{
+ Datum values[Natts_pg_attribute];
+ bool nulls[Natts_pg_attribute];
+ HeapTuple tup;
+
+ /* This is a tad tedious, but way cleaner than what we used to do... */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+
+ values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
+ values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
+ values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
+ values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
+ values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
+ values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
+ values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
+ values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
+ values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
+ values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
+ values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
+ values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
+ values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
+ values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
+ values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(new_attribute->atthasmissing);
+ values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
+ values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(new_attribute->attgenerated);
+ values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
+ values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
+ values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
+ values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
+ values[Anum_pg_attribute_attoptions - 1] = attoptions;
+
+ /* start out with empty permissions and empty options */
+ nulls[Anum_pg_attribute_attacl - 1] = true;
+ nulls[Anum_pg_attribute_attoptions - 1] = attoptions == (Datum) 0;
+ nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
+ nulls[Anum_pg_attribute_attmissingval - 1] = true;
+
+ tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
+
+ /* finally insert the new tuple, update the indexes, and clean up */
+ if (indstate != NULL)
+ CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
+ else
+ CatalogTupleInsert(pg_attribute_rel, tup);
+
+ heap_freetuple(tup);
+}
+
+/* --------------------------------
+ * AddNewAttributeTuples
+ *
+ * this registers the new relation's schema by adding
+ * tuples to pg_attribute.
+ * --------------------------------
+ */
+static void
+AddNewAttributeTuples(Oid new_rel_oid,
+ TupleDesc tupdesc,
+ char relkind)
+{
+ Form_pg_attribute attr;
+ int i;
+ Relation rel;
+ CatalogIndexState indstate;
+ int natts = tupdesc->natts;
+ ObjectAddress myself,
+ referenced;
+
+ /*
+ * open pg_attribute and its indexes.
+ */
+ rel = table_open(AttributeRelationId, RowExclusiveLock);
+
+ indstate = CatalogOpenIndexes(rel);
+
+ /*
+ * First we add the user attributes. This is also a convenient place to
+ * add dependencies on their datatypes and collations.
+ */
+ for (i = 0; i < natts; i++)
+ {
+ attr = TupleDescAttr(tupdesc, i);
+ /* Fill in the correct relation OID */
+ attr->attrelid = new_rel_oid;
+ /* Make sure this is OK, too */
+ attr->attstattarget = -1;
+
+ InsertPgAttributeTuple(rel, attr, (Datum) 0, indstate);
+
+ /* Add dependency info */
+ myself.classId = RelationRelationId;
+ myself.objectId = new_rel_oid;
+ myself.objectSubId = i + 1;
+ referenced.classId = TypeRelationId;
+ referenced.objectId = attr->atttypid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* The default collation is pinned, so don't bother recording it */
+ if (OidIsValid(attr->attcollation) &&
+ attr->attcollation != DEFAULT_COLLATION_OID)
+ {
+ referenced.classId = CollationRelationId;
+ referenced.objectId = attr->attcollation;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+ }
+
+ /*
+ * Next we add the system attributes. Skip OID if rel has no OIDs. Skip
+ * all for a view or type relation. We don't bother with making datatype
+ * dependencies here, since presumably all these types are pinned.
+ */
+ if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
+ {
+ for (i = 0; i < (int) lengthof(SysAtt); i++)
+ {
+ FormData_pg_attribute attStruct;
+
+ memcpy(&attStruct, SysAtt[i], sizeof(FormData_pg_attribute));
+
+ /* Fill in the correct relation OID in the copied tuple */
+ attStruct.attrelid = new_rel_oid;
+
+ InsertPgAttributeTuple(rel, &attStruct, (Datum) 0, indstate);
+ }
+ }
+
+ /*
+ * clean up
+ */
+ CatalogCloseIndexes(indstate);
+
+ table_close(rel, RowExclusiveLock);
+}
+
+/* --------------------------------
+ * InsertPgClassTuple
+ *
+ * Construct and insert a new tuple in pg_class.
+ *
+ * Caller has already opened and locked pg_class.
+ * Tuple data is taken from new_rel_desc->rd_rel, except for the
+ * variable-width fields which are not present in a cached reldesc.
+ * relacl and reloptions are passed in Datum form (to avoid having
+ * to reference the data types in heap.h). Pass (Datum) 0 to set them
+ * to NULL.
+ * --------------------------------
+ */
+void
+InsertPgClassTuple(Relation pg_class_desc,
+ Relation new_rel_desc,
+ Oid new_rel_oid,
+ Datum relacl,
+ Datum reloptions)
+{
+ Form_pg_class rd_rel = new_rel_desc->rd_rel;
+ Datum values[Natts_pg_class];
+ bool nulls[Natts_pg_class];
+ HeapTuple tup;
+
+ /* This is a tad tedious, but way cleaner than what we used to do... */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+
+ values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid);
+ values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
+ values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
+ values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
+ values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
+ values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
+ values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
+ values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
+ values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
+ values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
+ values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
+ values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
+ values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
+ values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
+ values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
+ values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
+ values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
+ values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
+ values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
+ values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
+ values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
+ values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
+ values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
+ values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
+ values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
+ values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
+ values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
+ values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
+ values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
+ values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
+ if (relacl != (Datum) 0)
+ values[Anum_pg_class_relacl - 1] = relacl;
+ else
+ nulls[Anum_pg_class_relacl - 1] = true;
+ if (reloptions != (Datum) 0)
+ values[Anum_pg_class_reloptions - 1] = reloptions;
+ else
+ nulls[Anum_pg_class_reloptions - 1] = true;
+
+ /* relpartbound is set by updating this tuple, if necessary */
+ nulls[Anum_pg_class_relpartbound - 1] = true;
+
+ tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
+
+ /* finally insert the new tuple, update the indexes, and clean up */
+ CatalogTupleInsert(pg_class_desc, tup);
+
+ heap_freetuple(tup);
+}
+
+/* --------------------------------
+ * AddNewRelationTuple
+ *
+ * this registers the new relation in the catalogs by
+ * adding a tuple to pg_class.
+ * --------------------------------
+ */
+static void
+AddNewRelationTuple(Relation pg_class_desc,
+ Relation new_rel_desc,
+ Oid new_rel_oid,
+ Oid new_type_oid,
+ Oid reloftype,
+ Oid relowner,
+ char relkind,
+ TransactionId relfrozenxid,
+ TransactionId relminmxid,
+ Datum relacl,
+ Datum reloptions)
+{
+ Form_pg_class new_rel_reltup;
+
+ /*
+ * first we update some of the information in our uncataloged relation's
+ * relation descriptor.
+ */
+ new_rel_reltup = new_rel_desc->rd_rel;
+
+ switch (relkind)
+ {
+ case RELKIND_RELATION:
+ case RELKIND_MATVIEW:
+ case RELKIND_INDEX:
+ case RELKIND_TOASTVALUE:
+ /* The relation is real, but as yet empty */
+ new_rel_reltup->relpages = 0;
+ new_rel_reltup->reltuples = 0;
+ new_rel_reltup->relallvisible = 0;
+ break;
+ case RELKIND_SEQUENCE:
+ /* Sequences always have a known size */
+ new_rel_reltup->relpages = 1;
+ new_rel_reltup->reltuples = 1;
+ new_rel_reltup->relallvisible = 0;
+ break;
+ default:
+ /* Views, etc, have no disk storage */
+ new_rel_reltup->relpages = 0;
+ new_rel_reltup->reltuples = 0;
+ new_rel_reltup->relallvisible = 0;
+ break;
+ }
+
+ new_rel_reltup->relfrozenxid = relfrozenxid;
+ new_rel_reltup->relminmxid = relminmxid;
+ new_rel_reltup->relowner = relowner;
+ new_rel_reltup->reltype = new_type_oid;
+ new_rel_reltup->reloftype = reloftype;
+
+ /* relispartition is always set by updating this tuple later */
+ new_rel_reltup->relispartition = false;
+
+ new_rel_desc->rd_att->tdtypeid = new_type_oid;
+
+ /* Now build and insert the tuple */
+ InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid,
+ relacl, reloptions);
+}
+
+
+/* --------------------------------
+ * AddNewRelationType -
+ *
+ * define a composite type corresponding to the new relation
+ * --------------------------------
+ */
+static ObjectAddress
+AddNewRelationType(const char *typeName,
+ Oid typeNamespace,
+ Oid new_rel_oid,
+ char new_rel_kind,
+ Oid ownerid,
+ Oid new_row_type,
+ Oid new_array_type)
+{
+ return
+ TypeCreate(new_row_type, /* optional predetermined OID */
+ typeName, /* type name */
+ typeNamespace, /* type namespace */
+ new_rel_oid, /* relation oid */
+ new_rel_kind, /* relation kind */
+ ownerid, /* owner's ID */
+ -1, /* internal size (varlena) */
+ TYPTYPE_COMPOSITE, /* type-type (composite) */
+ TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
+ false, /* composite types are never preferred */
+ DEFAULT_TYPDELIM, /* default array delimiter */
+ F_RECORD_IN, /* input procedure */
+ F_RECORD_OUT, /* output procedure */
+ F_RECORD_RECV, /* receive procedure */
+ F_RECORD_SEND, /* send procedure */
+ InvalidOid, /* typmodin procedure - none */
+ InvalidOid, /* typmodout procedure - none */
+ InvalidOid, /* analyze procedure - default */
+ InvalidOid, /* array element type - irrelevant */
+ false, /* this is not an array type */
+ new_array_type, /* array type if any */
+ InvalidOid, /* domain base type - irrelevant */
+ NULL, /* default value - none */
+ NULL, /* default binary representation */
+ false, /* passed by reference */
+ TYPALIGN_DOUBLE, /* alignment - must be the largest! */
+ TYPSTORAGE_EXTENDED, /* fully TOASTable */
+ -1, /* typmod */
+ 0, /* array dimensions for typBaseType */
+ false, /* Type NOT NULL */
+ InvalidOid); /* rowtypes never have a collation */
+}
+
+/* --------------------------------
+ * heap_create_with_catalog
+ *
+ * creates a new cataloged relation. see comments above.
+ *
+ * Arguments:
+ * relname: name to give to new rel
+ * relnamespace: OID of namespace it goes in
+ * reltablespace: OID of tablespace it goes in
+ * relid: OID to assign to new rel, or InvalidOid to select a new OID
+ * reltypeid: OID to assign to rel's rowtype, or InvalidOid to select one
+ * reloftypeid: if a typed table, OID of underlying type; else InvalidOid
+ * ownerid: OID of new rel's owner
+ * tupdesc: tuple descriptor (source of column definitions)
+ * cooked_constraints: list of precooked check constraints and defaults
+ * relkind: relkind for new rel
+ * relpersistence: rel's persistence status (permanent, temp, or unlogged)
+ * shared_relation: true if it's to be a shared relation
+ * mapped_relation: true if the relation will use the relfilenode map
+ * oncommit: ON COMMIT marking (only relevant if it's a temp table)
+ * reloptions: reloptions in Datum form, or (Datum) 0 if none
+ * use_user_acl: true if should look for user-defined default permissions;
+ * if false, relacl is always set NULL
+ * allow_system_table_mods: true to allow creation in system namespaces
+ * is_internal: is this a system-generated catalog?
+ *
+ * Output parameters:
+ * typaddress: if not null, gets the object address of the new pg_type entry
+ *
+ * Returns the OID of the new relation
+ * --------------------------------
+ */
+Oid
+heap_create_with_catalog(const char *relname,
+ Oid relnamespace,
+ Oid reltablespace,
+ Oid relid,
+ Oid reltypeid,
+ Oid reloftypeid,
+ Oid ownerid,
+ Oid accessmtd,
+ TupleDesc tupdesc,
+ List *cooked_constraints,
+ char relkind,
+ char relpersistence,
+ bool shared_relation,
+ bool mapped_relation,
+ OnCommitAction oncommit,
+ Datum reloptions,
+ bool use_user_acl,
+ bool allow_system_table_mods,
+ bool is_internal,
+ Oid relrewrite,
+ ObjectAddress *typaddress)
+{
+ Relation pg_class_desc;
+ Relation new_rel_desc;
+ Acl *relacl;
+ Oid existing_relid;
+ Oid old_type_oid;
+ Oid new_type_oid;
+ ObjectAddress new_type_addr;
+ Oid new_array_oid = InvalidOid;
+ TransactionId relfrozenxid;
+ MultiXactId relminmxid;
+
+ pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
+
+ /*
+ * sanity checks
+ */
+ Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
+
+ /*
+ * Validate proposed tupdesc for the desired relkind. If
+ * allow_system_table_mods is on, allow ANYARRAY to be used; this is a
+ * hack to allow creating pg_statistic and cloning it during VACUUM FULL.
+ */
+ CheckAttributeNamesTypes(tupdesc, relkind,
+ allow_system_table_mods ? CHKATYPE_ANYARRAY : 0);
+
+ /*
+ * This would fail later on anyway, if the relation already exists. But
+ * by catching it here we can emit a nicer error message.
+ */
+ existing_relid = get_relname_relid(relname, relnamespace);
+ if (existing_relid != InvalidOid)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_TABLE),
+ errmsg("relation \"%s\" already exists", relname)));
+
+ /*
+ * Since we are going to create a rowtype as well, also check for
+ * collision with an existing type name. If there is one and it's an
+ * autogenerated array, we can rename it out of the way; otherwise we can
+ * at least give a good error message.
+ */
+ old_type_oid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
+ CStringGetDatum(relname),
+ ObjectIdGetDatum(relnamespace));
+ if (OidIsValid(old_type_oid))
+ {
+ if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("type \"%s\" already exists", relname),
+ errhint("A relation has an associated type of the same name, "
+ "so you must use a name that doesn't conflict "
+ "with any existing type.")));
+ }
+
+ /*
+ * Shared relations must be in pg_global (last-ditch check)
+ */
+ if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
+ elog(ERROR, "shared relations must be placed in pg_global tablespace");
+
+ /*
+ * Allocate an OID for the relation, unless we were told what to use.
+ *
+ * The OID will be the relfilenode as well, so make sure it doesn't
+ * collide with either pg_class OIDs or existing physical files.
+ */
+ if (!OidIsValid(relid))
+ {
+ /* Use binary-upgrade override for pg_class.oid/relfilenode? */
+ if (IsBinaryUpgrade &&
+ (relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
+ relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
+ relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE ||
+ relkind == RELKIND_PARTITIONED_TABLE))
+ {
+ if (!OidIsValid(binary_upgrade_next_heap_pg_class_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("pg_class heap OID value not set when in binary upgrade mode")));
+
+ relid = binary_upgrade_next_heap_pg_class_oid;
+ binary_upgrade_next_heap_pg_class_oid = InvalidOid;
+ }
+ /* There might be no TOAST table, so we have to test for it. */
+ else if (IsBinaryUpgrade &&
+ OidIsValid(binary_upgrade_next_toast_pg_class_oid) &&
+ relkind == RELKIND_TOASTVALUE)
+ {
+ relid = binary_upgrade_next_toast_pg_class_oid;
+ binary_upgrade_next_toast_pg_class_oid = InvalidOid;
+ }
+ else
+ relid = GetNewRelFileNode(reltablespace, pg_class_desc,
+ relpersistence);
+ }
+
+ /*
+ * Determine the relation's initial permissions.
+ */
+ if (use_user_acl)
+ {
+ switch (relkind)
+ {
+ case RELKIND_RELATION:
+ case RELKIND_VIEW:
+ case RELKIND_MATVIEW:
+ case RELKIND_FOREIGN_TABLE:
+ case RELKIND_PARTITIONED_TABLE:
+ relacl = get_user_default_acl(OBJECT_TABLE, ownerid,
+ relnamespace);
+ break;
+ case RELKIND_SEQUENCE:
+ relacl = get_user_default_acl(OBJECT_SEQUENCE, ownerid,
+ relnamespace);
+ break;
+ default:
+ relacl = NULL;
+ break;
+ }
+ }
+ else
+ relacl = NULL;
+
+ /*
+ * Create the relcache entry (mostly dummy at this point) and the physical
+ * disk file. (If we fail further down, it's the smgr's responsibility to
+ * remove the disk file again.)
+ */
+ new_rel_desc = heap_create(relname,
+ relnamespace,
+ reltablespace,
+ relid,
+ InvalidOid,
+ accessmtd,
+ tupdesc,
+ relkind,
+ relpersistence,
+ shared_relation,
+ mapped_relation,
+ allow_system_table_mods,
+ &relfrozenxid,
+ &relminmxid);
+
+ Assert(relid == RelationGetRelid(new_rel_desc));
+
+ new_rel_desc->rd_rel->relrewrite = relrewrite;
+
+ /*
+ * Decide whether to create an array type over the relation's rowtype. We
+ * do not create any array types for system catalogs (ie, those made
+ * during initdb). We do not create them where the use of a relation as
+ * such is an implementation detail: toast tables, sequences and indexes.
+ */
+ if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
+ relkind == RELKIND_VIEW ||
+ relkind == RELKIND_MATVIEW ||
+ relkind == RELKIND_FOREIGN_TABLE ||
+ relkind == RELKIND_COMPOSITE_TYPE ||
+ relkind == RELKIND_PARTITIONED_TABLE))
+ new_array_oid = AssignTypeArrayOid();
+
+ /*
+ * Since defining a relation also defines a complex type, we add a new
+ * system type corresponding to the new relation. The OID of the type can
+ * be preselected by the caller, but if reltypeid is InvalidOid, we'll
+ * generate a new OID for it.
+ *
+ * NOTE: we could get a unique-index failure here, in case someone else is
+ * creating the same type name in parallel but hadn't committed yet when
+ * we checked for a duplicate name above.
+ */
+ new_type_addr = AddNewRelationType(relname,
+ relnamespace,
+ relid,
+ relkind,
+ ownerid,
+ reltypeid,
+ new_array_oid);
+ new_type_oid = new_type_addr.objectId;
+ if (typaddress)
+ *typaddress = new_type_addr;
+
+ /*
+ * Now make the array type if wanted.
+ */
+ if (OidIsValid(new_array_oid))
+ {
+ char *relarrayname;
+
+ relarrayname = makeArrayTypeName(relname, relnamespace);
+
+ TypeCreate(new_array_oid, /* force the type's OID to this */
+ relarrayname, /* Array type name */
+ relnamespace, /* Same namespace as parent */
+ InvalidOid, /* Not composite, no relationOid */
+ 0, /* relkind, also N/A here */
+ ownerid, /* owner's ID */
+ -1, /* Internal size (varlena) */
+ TYPTYPE_BASE, /* Not composite - typelem is */
+ TYPCATEGORY_ARRAY, /* type-category (array) */
+ false, /* array types are never preferred */
+ DEFAULT_TYPDELIM, /* default array delimiter */
+ F_ARRAY_IN, /* array input proc */
+ F_ARRAY_OUT, /* array output proc */
+ F_ARRAY_RECV, /* array recv (bin) proc */
+ F_ARRAY_SEND, /* array send (bin) proc */
+ InvalidOid, /* typmodin procedure - none */
+ InvalidOid, /* typmodout procedure - none */
+ F_ARRAY_TYPANALYZE, /* array analyze procedure */
+ new_type_oid, /* array element type - the rowtype */
+ true, /* yes, this is an array type */
+ InvalidOid, /* this has no array type */
+ InvalidOid, /* domain base type - irrelevant */
+ NULL, /* default value - none */
+ NULL, /* default binary representation */
+ false, /* passed by reference */
+ TYPALIGN_DOUBLE, /* alignment - must be the largest! */
+ TYPSTORAGE_EXTENDED, /* fully TOASTable */
+ -1, /* typmod */
+ 0, /* array dimensions for typBaseType */
+ false, /* Type NOT NULL */
+ InvalidOid); /* rowtypes never have a collation */
+
+ pfree(relarrayname);
+ }
+
+ /*
+ * now create an entry in pg_class for the relation.
+ *
+ * NOTE: we could get a unique-index failure here, in case someone else is
+ * creating the same relation name in parallel but hadn't committed yet
+ * when we checked for a duplicate name above.
+ */
+ AddNewRelationTuple(pg_class_desc,
+ new_rel_desc,
+ relid,
+ new_type_oid,
+ reloftypeid,
+ ownerid,
+ relkind,
+ relfrozenxid,
+ relminmxid,
+ PointerGetDatum(relacl),
+ reloptions);
+
+ /*
+ * now add tuples to pg_attribute for the attributes in our new relation.
+ */
+ AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind);
+
+ /*
+ * Make a dependency link to force the relation to be deleted if its
+ * namespace is. Also make a dependency link to its owner, as well as
+ * dependencies for any roles mentioned in the default ACL.
+ *
+ * For composite types, these dependencies are tracked for the pg_type
+ * entry, so we needn't record them here. Likewise, TOAST tables don't
+ * need a namespace dependency (they live in a pinned namespace) nor an
+ * owner dependency (they depend indirectly through the parent table), nor
+ * should they have any ACL entries. The same applies for extension
+ * dependencies.
+ *
+ * Also, skip this in bootstrap mode, since we don't make dependencies
+ * while bootstrapping.
+ */
+ if (relkind != RELKIND_COMPOSITE_TYPE &&
+ relkind != RELKIND_TOASTVALUE &&
+ !IsBootstrapProcessingMode())
+ {
+ ObjectAddress myself,
+ referenced;
+
+ myself.classId = RelationRelationId;
+ myself.objectId = relid;
+ myself.objectSubId = 0;
+
+ referenced.classId = NamespaceRelationId;
+ referenced.objectId = relnamespace;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ recordDependencyOnOwner(RelationRelationId, relid, ownerid);
+
+ recordDependencyOnNewAcl(RelationRelationId, relid, 0, ownerid, relacl);
+
+ recordDependencyOnCurrentExtension(&myself, false);
+
+ if (reloftypeid)
+ {
+ referenced.classId = TypeRelationId;
+ referenced.objectId = reloftypeid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /*
+ * Make a dependency link to force the relation to be deleted if its
+ * access method is. Do this only for relation and materialized views.
+ *
+ * No need to add an explicit dependency for the toast table, as the
+ * main table depends on it.
+ */
+ if (relkind == RELKIND_RELATION ||
+ relkind == RELKIND_MATVIEW)
+ {
+ referenced.classId = AccessMethodRelationId;
+ referenced.objectId = accessmtd;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+ }
+
+ /* Post creation hook for new relation */
+ InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
+
+ /*
+ * Store any supplied constraints and defaults.
+ *
+ * NB: this may do a CommandCounterIncrement and rebuild the relcache
+ * entry, so the relation must be valid and self-consistent at this point.
+ * In particular, there are not yet constraints and defaults anywhere.
+ */
+ StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
+
+ /*
+ * If there's a special on-commit action, remember it
+ */
+ if (oncommit != ONCOMMIT_NOOP)
+ register_on_commit_action(relid, oncommit);
+
+ /*
+ * ok, the relation has been cataloged, so close our relations and return
+ * the OID of the newly created relation.
+ */
+ table_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
+ table_close(pg_class_desc, RowExclusiveLock);
+
+ return relid;
+}
+
+/*
+ * RelationRemoveInheritance
+ *
+ * Formerly, this routine checked for child relations and aborted the
+ * deletion if any were found. Now we rely on the dependency mechanism
+ * to check for or delete child relations. By the time we get here,
+ * there are no children and we need only remove any pg_inherits rows
+ * linking this relation to its parent(s).
+ */
+static void
+RelationRemoveInheritance(Oid relid)
+{
+ Relation catalogRelation;
+ SysScanDesc scan;
+ ScanKeyData key;
+ HeapTuple tuple;
+
+ catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key,
+ Anum_pg_inherits_inhrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+
+ scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
+ NULL, 1, &key);
+
+ while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ CatalogTupleDelete(catalogRelation, &tuple->t_self);
+
+ systable_endscan(scan);
+ table_close(catalogRelation, RowExclusiveLock);
+}
+
+/*
+ * DeleteRelationTuple
+ *
+ * Remove pg_class row for the given relid.
+ *
+ * Note: this is shared by relation deletion and index deletion. It's
+ * not intended for use anyplace else.
+ */
+void
+DeleteRelationTuple(Oid relid)
+{
+ Relation pg_class_desc;
+ HeapTuple tup;
+
+ /* Grab an appropriate lock on the pg_class relation */
+ pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
+
+ tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+
+ /* delete the relation tuple from pg_class, and finish up */
+ CatalogTupleDelete(pg_class_desc, &tup->t_self);
+
+ ReleaseSysCache(tup);
+
+ table_close(pg_class_desc, RowExclusiveLock);
+}
+
+/*
+ * DeleteAttributeTuples
+ *
+ * Remove pg_attribute rows for the given relid.
+ *
+ * Note: this is shared by relation deletion and index deletion. It's
+ * not intended for use anyplace else.
+ */
+void
+DeleteAttributeTuples(Oid relid)
+{
+ Relation attrel;
+ SysScanDesc scan;
+ ScanKeyData key[1];
+ HeapTuple atttup;
+
+ /* Grab an appropriate lock on the pg_attribute relation */
+ attrel = table_open(AttributeRelationId, RowExclusiveLock);
+
+ /* Use the index to scan only attributes of the target relation */
+ ScanKeyInit(&key[0],
+ Anum_pg_attribute_attrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+
+ scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
+ NULL, 1, key);
+
+ /* Delete all the matching tuples */
+ while ((atttup = systable_getnext(scan)) != NULL)
+ CatalogTupleDelete(attrel, &atttup->t_self);
+
+ /* Clean up after the scan */
+ systable_endscan(scan);
+ table_close(attrel, RowExclusiveLock);
+}
+
+/*
+ * DeleteSystemAttributeTuples
+ *
+ * Remove pg_attribute rows for system columns of the given relid.
+ *
+ * Note: this is only used when converting a table to a view. Views don't
+ * have system columns, so we should remove them from pg_attribute.
+ */
+void
+DeleteSystemAttributeTuples(Oid relid)
+{
+ Relation attrel;
+ SysScanDesc scan;
+ ScanKeyData key[2];
+ HeapTuple atttup;
+
+ /* Grab an appropriate lock on the pg_attribute relation */
+ attrel = table_open(AttributeRelationId, RowExclusiveLock);
+
+ /* Use the index to scan only system attributes of the target relation */
+ ScanKeyInit(&key[0],
+ Anum_pg_attribute_attrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ ScanKeyInit(&key[1],
+ Anum_pg_attribute_attnum,
+ BTLessEqualStrategyNumber, F_INT2LE,
+ Int16GetDatum(0));
+
+ scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
+ NULL, 2, key);
+
+ /* Delete all the matching tuples */
+ while ((atttup = systable_getnext(scan)) != NULL)
+ CatalogTupleDelete(attrel, &atttup->t_self);
+
+ /* Clean up after the scan */
+ systable_endscan(scan);
+ table_close(attrel, RowExclusiveLock);
+}
+
+/*
+ * RemoveAttributeById
+ *
+ * This is the guts of ALTER TABLE DROP COLUMN: actually mark the attribute
+ * deleted in pg_attribute. We also remove pg_statistic entries for it.
+ * (Everything else needed, such as getting rid of any pg_attrdef entry,
+ * is handled by dependency.c.)
+ */
+void
+RemoveAttributeById(Oid relid, AttrNumber attnum)
+{
+ Relation rel;
+ Relation attr_rel;
+ HeapTuple tuple;
+ Form_pg_attribute attStruct;
+ char newattname[NAMEDATALEN];
+
+ /*
+ * Grab an exclusive lock on the target table, which we will NOT release
+ * until end of transaction. (In the simple case where we are directly
+ * dropping this column, ATExecDropColumn already did this ... but when
+ * cascading from a drop of some other object, we may not have any lock.)
+ */
+ rel = relation_open(relid, AccessExclusiveLock);
+
+ attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCacheCopy2(ATTNUM,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(attnum));
+ if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
+ elog(ERROR, "cache lookup failed for attribute %d of relation %u",
+ attnum, relid);
+ attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
+
+ if (attnum < 0)
+ {
+ /* System attribute (probably OID) ... just delete the row */
+
+ CatalogTupleDelete(attr_rel, &tuple->t_self);
+ }
+ else
+ {
+ /* Dropping user attributes is lots harder */
+
+ /* Mark the attribute as dropped */
+ attStruct->attisdropped = true;
+
+ /*
+ * Set the type OID to invalid. A dropped attribute's type link
+ * cannot be relied on (once the attribute is dropped, the type might
+ * be too). Fortunately we do not need the type row --- the only
+ * really essential information is the type's typlen and typalign,
+ * which are preserved in the attribute's attlen and attalign. We set
+ * atttypid to zero here as a means of catching code that incorrectly
+ * expects it to be valid.
+ */
+ attStruct->atttypid = InvalidOid;
+
+ /* Remove any NOT NULL constraint the column may have */
+ attStruct->attnotnull = false;
+
+ /* We don't want to keep stats for it anymore */
+ attStruct->attstattarget = 0;
+
+ /* Unset this so no one tries to look up the generation expression */
+ attStruct->attgenerated = '\0';
+
+ /*
+ * Change the column name to something that isn't likely to conflict
+ */
+ snprintf(newattname, sizeof(newattname),
+ "........pg.dropped.%d........", attnum);
+ namestrcpy(&(attStruct->attname), newattname);
+
+ /* clear the missing value if any */
+ if (attStruct->atthasmissing)
+ {
+ Datum valuesAtt[Natts_pg_attribute];
+ bool nullsAtt[Natts_pg_attribute];
+ bool replacesAtt[Natts_pg_attribute];
+
+ /* update the tuple - set atthasmissing and attmissingval */
+ MemSet(valuesAtt, 0, sizeof(valuesAtt));
+ MemSet(nullsAtt, false, sizeof(nullsAtt));
+ MemSet(replacesAtt, false, sizeof(replacesAtt));
+
+ valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
+ BoolGetDatum(false);
+ replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
+ valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
+ nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
+ replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
+
+ tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
+ valuesAtt, nullsAtt, replacesAtt);
+ }
+
+ CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
+ }
+
+ /*
+ * Because updating the pg_attribute row will trigger a relcache flush for
+ * the target relation, we need not do anything else to notify other
+ * backends of the change.
+ */
+
+ table_close(attr_rel, RowExclusiveLock);
+
+ if (attnum > 0)
+ RemoveStatistics(relid, attnum);
+
+ relation_close(rel, NoLock);
+}
+
+/*
+ * RemoveAttrDefault
+ *
+ * If the specified relation/attribute has a default, remove it.
+ * (If no default, raise error if complain is true, else return quietly.)
+ */
+void
+RemoveAttrDefault(Oid relid, AttrNumber attnum,
+ DropBehavior behavior, bool complain, bool internal)
+{
+ Relation attrdef_rel;
+ ScanKeyData scankeys[2];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ bool found = false;
+
+ attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&scankeys[0],
+ Anum_pg_attrdef_adrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ ScanKeyInit(&scankeys[1],
+ Anum_pg_attrdef_adnum,
+ BTEqualStrategyNumber, F_INT2EQ,
+ Int16GetDatum(attnum));
+
+ scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
+ NULL, 2, scankeys);
+
+ /* There should be at most one matching tuple, but we loop anyway */
+ while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ {
+ ObjectAddress object;
+ Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
+
+ object.classId = AttrDefaultRelationId;
+ object.objectId = attrtuple->oid;
+ object.objectSubId = 0;
+
+ performDeletion(&object, behavior,
+ internal ? PERFORM_DELETION_INTERNAL : 0);
+
+ found = true;
+ }
+
+ systable_endscan(scan);
+ table_close(attrdef_rel, RowExclusiveLock);
+
+ if (complain && !found)
+ elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
+ relid, attnum);
+}
+
+/*
+ * RemoveAttrDefaultById
+ *
+ * Remove a pg_attrdef entry specified by OID. This is the guts of
+ * attribute-default removal. Note it should be called via performDeletion,
+ * not directly.
+ */
+void
+RemoveAttrDefaultById(Oid attrdefId)
+{
+ Relation attrdef_rel;
+ Relation attr_rel;
+ Relation myrel;
+ ScanKeyData scankeys[1];
+ SysScanDesc scan;
+ HeapTuple tuple;
+ Oid myrelid;
+ AttrNumber myattnum;
+
+ /* Grab an appropriate lock on the pg_attrdef relation */
+ attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
+
+ /* Find the pg_attrdef tuple */
+ ScanKeyInit(&scankeys[0],
+ Anum_pg_attrdef_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(attrdefId));
+
+ scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
+ NULL, 1, scankeys);
+
+ tuple = systable_getnext(scan);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
+
+ myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
+ myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
+
+ /* Get an exclusive lock on the relation owning the attribute */
+ myrel = relation_open(myrelid, AccessExclusiveLock);
+
+ /* Now we can delete the pg_attrdef row */
+ CatalogTupleDelete(attrdef_rel, &tuple->t_self);
+
+ systable_endscan(scan);
+ table_close(attrdef_rel, RowExclusiveLock);
+
+ /* Fix the pg_attribute row */
+ attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCacheCopy2(ATTNUM,
+ ObjectIdGetDatum(myrelid),
+ Int16GetDatum(myattnum));
+ if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
+ elog(ERROR, "cache lookup failed for attribute %d of relation %u",
+ myattnum, myrelid);
+
+ ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
+
+ CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
+
+ /*
+ * Our update of the pg_attribute row will force a relcache rebuild, so
+ * there's nothing else to do here.
+ */
+ table_close(attr_rel, RowExclusiveLock);
+
+ /* Keep lock on attribute's rel until end of xact */
+ relation_close(myrel, NoLock);
+}
+
+/*
+ * heap_drop_with_catalog - removes specified relation from catalogs
+ *
+ * Note that this routine is not responsible for dropping objects that are
+ * linked to the pg_class entry via dependencies (for example, indexes and
+ * constraints). Those are deleted by the dependency-tracing logic in
+ * dependency.c before control gets here. In general, therefore, this routine
+ * should never be called directly; go through performDeletion() instead.
+ */
+void
+heap_drop_with_catalog(Oid relid)
+{
+ Relation rel;
+ HeapTuple tuple;
+ Oid parentOid = InvalidOid,
+ defaultPartOid = InvalidOid;
+
+ /*
+ * To drop a partition safely, we must grab exclusive lock on its parent,
+ * because another backend might be about to execute a query on the parent
+ * table. If it relies on previously cached partition descriptor, then it
+ * could attempt to access the just-dropped relation as its partition. We
+ * must therefore take a table lock strong enough to prevent all queries
+ * on the table from proceeding until we commit and send out a
+ * shared-cache-inval notice that will make them update their partition
+ * descriptors.
+ */
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+ if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
+ {
+ parentOid = get_partition_parent(relid);
+ LockRelationOid(parentOid, AccessExclusiveLock);
+
+ /*
+ * If this is not the default partition, dropping it will change the
+ * default partition's partition constraint, so we must lock it.
+ */
+ defaultPartOid = get_default_partition_oid(parentOid);
+ if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
+ LockRelationOid(defaultPartOid, AccessExclusiveLock);
+ }
+
+ ReleaseSysCache(tuple);
+
+ /*
+ * Open and lock the relation.
+ */
+ rel = relation_open(relid, AccessExclusiveLock);
+
+ /*
+ * There can no longer be anyone *else* touching the relation, but we
+ * might still have open queries or cursors, or pending trigger events, in
+ * our own session.
+ */
+ CheckTableNotInUse(rel, "DROP TABLE");
+
+ /*
+ * This effectively deletes all rows in the table, and may be done in a
+ * serializable transaction. In that case we must record a rw-conflict in
+ * to this transaction from each transaction holding a predicate lock on
+ * the table.
+ */
+ CheckTableForSerializableConflictIn(rel);
+
+ /*
+ * Delete pg_foreign_table tuple first.
+ */
+ if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
+ {
+ Relation rel;
+ HeapTuple tuple;
+
+ rel = table_open(ForeignTableRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for foreign table %u", relid);
+
+ CatalogTupleDelete(rel, &tuple->t_self);
+
+ ReleaseSysCache(tuple);
+ table_close(rel, RowExclusiveLock);
+ }
+
+ /*
+ * If a partitioned table, delete the pg_partitioned_table tuple.
+ */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ RemovePartitionKeyByRelId(relid);
+
+ /*
+ * If the relation being dropped is the default partition itself,
+ * invalidate its entry in pg_partitioned_table.
+ */
+ if (relid == defaultPartOid)
+ update_default_partition_oid(parentOid, InvalidOid);
+
+ /*
+ * Schedule unlinking of the relation's physical files at commit.
+ */
+ if (rel->rd_rel->relkind != RELKIND_VIEW &&
+ rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
+ rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ {
+ RelationDropStorage(rel);
+ }
+
+ /*
+ * Close relcache entry, but *keep* AccessExclusiveLock on the relation
+ * until transaction commit. This ensures no one else will try to do
+ * something with the doomed relation.
+ */
+ relation_close(rel, NoLock);
+
+ /*
+ * Remove any associated relation synchronization states.
+ */
+ RemoveSubscriptionRel(InvalidOid, relid);
+
+ /*
+ * Forget any ON COMMIT action for the rel
+ */
+ remove_on_commit_action(relid);
+
+ /*
+ * Flush the relation from the relcache. We want to do this before
+ * starting to remove catalog entries, just to be certain that no relcache
+ * entry rebuild will happen partway through. (That should not really
+ * matter, since we don't do CommandCounterIncrement here, but let's be
+ * safe.)
+ */
+ RelationForgetRelation(relid);
+
+ /*
+ * remove inheritance information
+ */
+ RelationRemoveInheritance(relid);
+
+ /*
+ * delete statistics
+ */
+ RemoveStatistics(relid, 0);
+
+ /*
+ * delete attribute tuples
+ */
+ DeleteAttributeTuples(relid);
+
+ /*
+ * delete relation tuple
+ */
+ DeleteRelationTuple(relid);
+
+ if (OidIsValid(parentOid))
+ {
+ /*
+ * If this is not the default partition, the partition constraint of
+ * the default partition has changed to include the portion of the key
+ * space previously covered by the dropped partition.
+ */
+ if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
+ CacheInvalidateRelcacheByRelid(defaultPartOid);
+
+ /*
+ * Invalidate the parent's relcache so that the partition is no longer
+ * included in its partition descriptor.
+ */
+ CacheInvalidateRelcacheByRelid(parentOid);
+ /* keep the lock */
+ }
+}
+
+
+/*
+ * RelationClearMissing
+ *
+ * Set atthasmissing and attmissingval to false/null for all attributes
+ * where they are currently set. This can be safely and usefully done if
+ * the table is rewritten (e.g. by VACUUM FULL or CLUSTER) where we know there
+ * are no rows left with less than a full complement of attributes.
+ *
+ * The caller must have an AccessExclusive lock on the relation.
+ */
+void
+RelationClearMissing(Relation rel)
+{
+ Relation attr_rel;
+ Oid relid = RelationGetRelid(rel);
+ int natts = RelationGetNumberOfAttributes(rel);
+ int attnum;
+ Datum repl_val[Natts_pg_attribute];
+ bool repl_null[Natts_pg_attribute];
+ bool repl_repl[Natts_pg_attribute];
+ Form_pg_attribute attrtuple;
+ HeapTuple tuple,
+ newtuple;
+
+ memset(repl_val, 0, sizeof(repl_val));
+ memset(repl_null, false, sizeof(repl_null));
+ memset(repl_repl, false, sizeof(repl_repl));
+
+ repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
+ repl_null[Anum_pg_attribute_attmissingval - 1] = true;
+
+ repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
+ repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
+
+
+ /* Get a lock on pg_attribute */
+ attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
+
+ /* process each non-system attribute, including any dropped columns */
+ for (attnum = 1; attnum <= natts; attnum++)
+ {
+ tuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(attnum));
+ if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
+ elog(ERROR, "cache lookup failed for attribute %d of relation %u",
+ attnum, relid);
+
+ attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
+
+ /* ignore any where atthasmissing is not true */
+ if (attrtuple->atthasmissing)
+ {
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
+ repl_val, repl_null, repl_repl);
+
+ CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
+
+ heap_freetuple(newtuple);
+ }
+
+ ReleaseSysCache(tuple);
+ }
+
+ /*
+ * Our update of the pg_attribute rows will force a relcache rebuild, so
+ * there's nothing else to do here.
+ */
+ table_close(attr_rel, RowExclusiveLock);
+}
+
+/*
+ * SetAttrMissing
+ *
+ * Set the missing value of a single attribute. This should only be used by
+ * binary upgrade. Takes an AccessExclusive lock on the relation owning the
+ * attribute.
+ */
+void
+SetAttrMissing(Oid relid, char *attname, char *value)
+{
+ Datum valuesAtt[Natts_pg_attribute];
+ bool nullsAtt[Natts_pg_attribute];
+ bool replacesAtt[Natts_pg_attribute];
+ Datum missingval;
+ Form_pg_attribute attStruct;
+ Relation attrrel,
+ tablerel;
+ HeapTuple atttup,
+ newtup;
+
+ /* lock the table the attribute belongs to */
+ tablerel = table_open(relid, AccessExclusiveLock);
+
+ /* Don't do anything unless it's a plain table */
+ if (tablerel->rd_rel->relkind != RELKIND_RELATION)
+ {
+ table_close(tablerel, AccessExclusiveLock);
+ return;
+ }
+
+ /* Lock the attribute row and get the data */
+ attrrel = table_open(AttributeRelationId, RowExclusiveLock);
+ atttup = SearchSysCacheAttName(relid, attname);
+ if (!HeapTupleIsValid(atttup))
+ elog(ERROR, "cache lookup failed for attribute %s of relation %u",
+ attname, relid);
+ attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
+
+ /* get an array value from the value string */
+ missingval = OidFunctionCall3(F_ARRAY_IN,
+ CStringGetDatum(value),
+ ObjectIdGetDatum(attStruct->atttypid),
+ Int32GetDatum(attStruct->atttypmod));
+
+ /* update the tuple - set atthasmissing and attmissingval */
+ MemSet(valuesAtt, 0, sizeof(valuesAtt));
+ MemSet(nullsAtt, false, sizeof(nullsAtt));
+ MemSet(replacesAtt, false, sizeof(replacesAtt));
+
+ valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
+ replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
+ valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
+ replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
+
+ newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
+ valuesAtt, nullsAtt, replacesAtt);
+ CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
+
+ /* clean up */
+ ReleaseSysCache(atttup);
+ table_close(attrrel, RowExclusiveLock);
+ table_close(tablerel, AccessExclusiveLock);
+}
+
+/*
+ * Store a default expression for column attnum of relation rel.
+ *
+ * Returns the OID of the new pg_attrdef tuple.
+ *
+ * add_column_mode must be true if we are storing the default for a new
+ * attribute, and false if it's for an already existing attribute. The reason
+ * for this is that the missing value must never be updated after it is set,
+ * which can only be when a column is added to the table. Otherwise we would
+ * in effect be changing existing tuples.
+ */
+Oid
+StoreAttrDefault(Relation rel, AttrNumber attnum,
+ Node *expr, bool is_internal, bool add_column_mode)
+{
+ char *adbin;
+ Relation adrel;
+ HeapTuple tuple;
+ Datum values[4];
+ static bool nulls[4] = {false, false, false, false};
+ Relation attrrel;
+ HeapTuple atttup;
+ Form_pg_attribute attStruct;
+ char attgenerated;
+ Oid attrdefOid;
+ ObjectAddress colobject,
+ defobject;
+
+ adrel = table_open(AttrDefaultRelationId, RowExclusiveLock);
+
+ /*
+ * Flatten expression to string form for storage.
+ */
+ adbin = nodeToString(expr);
+
+ /*
+ * Make the pg_attrdef entry.
+ */
+ attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId,
+ Anum_pg_attrdef_oid);
+ values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
+ values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
+ values[Anum_pg_attrdef_adnum - 1] = attnum;
+ values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
+
+ tuple = heap_form_tuple(adrel->rd_att, values, nulls);
+ CatalogTupleInsert(adrel, tuple);
+
+ defobject.classId = AttrDefaultRelationId;
+ defobject.objectId = attrdefOid;
+ defobject.objectSubId = 0;
+
+ table_close(adrel, RowExclusiveLock);
+
+ /* now can free some of the stuff allocated above */
+ pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
+ heap_freetuple(tuple);
+ pfree(adbin);
+
+ /*
+ * Update the pg_attribute entry for the column to show that a default
+ * exists.
+ */
+ attrrel = table_open(AttributeRelationId, RowExclusiveLock);
+ atttup = SearchSysCacheCopy2(ATTNUM,
+ ObjectIdGetDatum(RelationGetRelid(rel)),
+ Int16GetDatum(attnum));
+ if (!HeapTupleIsValid(atttup))
+ elog(ERROR, "cache lookup failed for attribute %d of relation %u",
+ attnum, RelationGetRelid(rel));
+ attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
+ attgenerated = attStruct->attgenerated;
+ if (!attStruct->atthasdef)
+ {
+ Form_pg_attribute defAttStruct;
+
+ ExprState *exprState;
+ Expr *expr2 = (Expr *) expr;
+ EState *estate = NULL;
+ ExprContext *econtext;
+ Datum valuesAtt[Natts_pg_attribute];
+ bool nullsAtt[Natts_pg_attribute];
+ bool replacesAtt[Natts_pg_attribute];
+ Datum missingval = (Datum) 0;
+ bool missingIsNull = true;
+
+ MemSet(valuesAtt, 0, sizeof(valuesAtt));
+ MemSet(nullsAtt, false, sizeof(nullsAtt));
+ MemSet(replacesAtt, false, sizeof(replacesAtt));
+ valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
+ replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
+
+ if (rel->rd_rel->relkind == RELKIND_RELATION && add_column_mode &&
+ !attgenerated)
+ {
+ expr2 = expression_planner(expr2);
+ estate = CreateExecutorState();
+ exprState = ExecPrepareExpr(expr2, estate);
+ econtext = GetPerTupleExprContext(estate);
+
+ missingval = ExecEvalExpr(exprState, econtext,
+ &missingIsNull);
+
+ FreeExecutorState(estate);
+
+ defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
+
+ if (missingIsNull)
+ {
+ /* if the default evaluates to NULL, just store a NULL array */
+ missingval = (Datum) 0;
+ }
+ else
+ {
+ /* otherwise make a one-element array of the value */
+ missingval = PointerGetDatum(construct_array(&missingval,
+ 1,
+ defAttStruct->atttypid,
+ defAttStruct->attlen,
+ defAttStruct->attbyval,
+ defAttStruct->attalign));
+ }
+
+ valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
+ replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
+ valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
+ replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
+ nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
+ }
+ atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
+ valuesAtt, nullsAtt, replacesAtt);
+
+ CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
+
+ if (!missingIsNull)
+ pfree(DatumGetPointer(missingval));
+
+ }
+ table_close(attrrel, RowExclusiveLock);
+ heap_freetuple(atttup);
+
+ /*
+ * Make a dependency so that the pg_attrdef entry goes away if the column
+ * (or whole table) is deleted.
+ */
+ colobject.classId = RelationRelationId;
+ colobject.objectId = RelationGetRelid(rel);
+ colobject.objectSubId = attnum;
+
+ recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
+
+ /*
+ * Record dependencies on objects used in the expression, too.
+ */
+ if (attgenerated)
+ {
+ /*
+ * Generated column: Dropping anything that the generation expression
+ * refers to automatically drops the generated column.
+ */
+ recordDependencyOnSingleRelExpr(&colobject, expr, RelationGetRelid(rel),
+ DEPENDENCY_AUTO,
+ DEPENDENCY_AUTO, false);
+ }
+ else
+ {
+ /*
+ * Normal default: Dropping anything that the default refers to
+ * requires CASCADE and drops the default only.
+ */
+ recordDependencyOnSingleRelExpr(&defobject, expr, RelationGetRelid(rel),
+ DEPENDENCY_NORMAL,
+ DEPENDENCY_NORMAL, false);
+ }
+
+ /*
+ * Post creation hook for attribute defaults.
+ *
+ * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
+ * couple of deletion/creation of the attribute's default entry, so the
+ * callee should check existence of an older version of this entry if it
+ * needs to distinguish.
+ */
+ InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
+ RelationGetRelid(rel), attnum, is_internal);
+
+ return attrdefOid;
+}
+
+/*
+ * Store a check-constraint expression for the given relation.
+ *
+ * Caller is responsible for updating the count of constraints
+ * in the pg_class entry for the relation.
+ *
+ * The OID of the new constraint is returned.
+ */
+static Oid
+StoreRelCheck(Relation rel, const char *ccname, Node *expr,
+ bool is_validated, bool is_local, int inhcount,
+ bool is_no_inherit, bool is_internal)
+{
+ char *ccbin;
+ List *varList;
+ int keycount;
+ int16 *attNos;
+ Oid constrOid;
+
+ /*
+ * Flatten expression to string form for storage.
+ */
+ ccbin = nodeToString(expr);
+
+ /*
+ * Find columns of rel that are used in expr
+ *
+ * NB: pull_var_clause is okay here only because we don't allow subselects
+ * in check constraints; it would fail to examine the contents of
+ * subselects.
+ */
+ varList = pull_var_clause(expr, 0);
+ keycount = list_length(varList);
+
+ if (keycount > 0)
+ {
+ ListCell *vl;
+ int i = 0;
+
+ attNos = (int16 *) palloc(keycount * sizeof(int16));
+ foreach(vl, varList)
+ {
+ Var *var = (Var *) lfirst(vl);
+ int j;
+
+ for (j = 0; j < i; j++)
+ if (attNos[j] == var->varattno)
+ break;
+ if (j == i)
+ attNos[i++] = var->varattno;
+ }
+ keycount = i;
+ }
+ else
+ attNos = NULL;
+
+ /*
+ * Partitioned tables do not contain any rows themselves, so a NO INHERIT
+ * constraint makes no sense.
+ */
+ if (is_no_inherit &&
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
+ RelationGetRelationName(rel))));
+
+ /*
+ * Create the Check Constraint
+ */
+ constrOid =
+ CreateConstraintEntry(ccname, /* Constraint Name */
+ RelationGetNamespace(rel), /* namespace */
+ CONSTRAINT_CHECK, /* Constraint Type */
+ false, /* Is Deferrable */
+ false, /* Is Deferred */
+ is_validated,
+ InvalidOid, /* no parent constraint */
+ RelationGetRelid(rel), /* relation */
+ attNos, /* attrs in the constraint */
+ keycount, /* # key attrs in the constraint */
+ keycount, /* # total attrs in the constraint */
+ InvalidOid, /* not a domain constraint */
+ InvalidOid, /* no associated index */
+ InvalidOid, /* Foreign key fields */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ ' ',
+ ' ',
+ ' ',
+ NULL, /* not an exclusion constraint */
+ expr, /* Tree form of check constraint */
+ ccbin, /* Binary form of check constraint */
+ is_local, /* conislocal */
+ inhcount, /* coninhcount */
+ is_no_inherit, /* connoinherit */
+ is_internal); /* internally constructed? */
+
+ pfree(ccbin);
+
+ return constrOid;
+}
+
+/*
+ * Store defaults and constraints (passed as a list of CookedConstraint).
+ *
+ * Each CookedConstraint struct is modified to store the new catalog tuple OID.
+ *
+ * NOTE: only pre-cooked expressions will be passed this way, which is to
+ * say expressions inherited from an existing relation. Newly parsed
+ * expressions can be added later, by direct calls to StoreAttrDefault
+ * and StoreRelCheck (see AddRelationNewConstraints()).
+ */
+static void
+StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
+{
+ int numchecks = 0;
+ ListCell *lc;
+
+ if (cooked_constraints == NIL)
+ return; /* nothing to do */
+
+ /*
+ * Deparsing of constraint expressions will fail unless the just-created
+ * pg_attribute tuples for this relation are made visible. So, bump the
+ * command counter. CAUTION: this will cause a relcache entry rebuild.
+ */
+ CommandCounterIncrement();
+
+ foreach(lc, cooked_constraints)
+ {
+ CookedConstraint *con = (CookedConstraint *) lfirst(lc);
+
+ switch (con->contype)
+ {
+ case CONSTR_DEFAULT:
+ con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
+ is_internal, false);
+ break;
+ case CONSTR_CHECK:
+ con->conoid =
+ StoreRelCheck(rel, con->name, con->expr,
+ !con->skip_validation, con->is_local,
+ con->inhcount, con->is_no_inherit,
+ is_internal);
+ numchecks++;
+ break;
+ default:
+ elog(ERROR, "unrecognized constraint type: %d",
+ (int) con->contype);
+ }
+ }
+
+ if (numchecks > 0)
+ SetRelationNumChecks(rel, numchecks);
+}
+
+/*
+ * AddRelationNewConstraints
+ *
+ * Add new column default expressions and/or constraint check expressions
+ * to an existing relation. This is defined to do both for efficiency in
+ * DefineRelation, but of course you can do just one or the other by passing
+ * empty lists.
+ *
+ * rel: relation to be modified
+ * newColDefaults: list of RawColumnDefault structures
+ * newConstraints: list of Constraint nodes
+ * allow_merge: true if check constraints may be merged with existing ones
+ * is_local: true if definition is local, false if it's inherited
+ * is_internal: true if result of some internal process, not a user request
+ *
+ * All entries in newColDefaults will be processed. Entries in newConstraints
+ * will be processed only if they are CONSTR_CHECK type.
+ *
+ * Returns a list of CookedConstraint nodes that shows the cooked form of
+ * the default and constraint expressions added to the relation.
+ *
+ * NB: caller should have opened rel with AccessExclusiveLock, and should
+ * hold that lock till end of transaction. Also, we assume the caller has
+ * done a CommandCounterIncrement if necessary to make the relation's catalog
+ * tuples visible.
+ */
+List *
+AddRelationNewConstraints(Relation rel,
+ List *newColDefaults,
+ List *newConstraints,
+ bool allow_merge,
+ bool is_local,
+ bool is_internal,
+ const char *queryString)
+{
+ List *cookedConstraints = NIL;
+ TupleDesc tupleDesc;
+ TupleConstr *oldconstr;
+ int numoldchecks;
+ ParseState *pstate;
+ ParseNamespaceItem *nsitem;
+ int numchecks;
+ List *checknames;
+ ListCell *cell;
+ Node *expr;
+ CookedConstraint *cooked;
+
+ /*
+ * Get info about existing constraints.
+ */
+ tupleDesc = RelationGetDescr(rel);
+ oldconstr = tupleDesc->constr;
+ if (oldconstr)
+ numoldchecks = oldconstr->num_check;
+ else
+ numoldchecks = 0;
+
+ /*
+ * Create a dummy ParseState and insert the target relation as its sole
+ * rangetable entry. We need a ParseState for transformExpr.
+ */
+ pstate = make_parsestate(NULL);
+ pstate->p_sourcetext = queryString;
+ nsitem = addRangeTableEntryForRelation(pstate,
+ rel,
+ AccessShareLock,
+ NULL,
+ false,
+ true);
+ addNSItemToQuery(pstate, nsitem, true, true, true);
+
+ /*
+ * Process column default expressions.
+ */
+ foreach(cell, newColDefaults)
+ {
+ RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
+ Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
+ Oid defOid;
+
+ expr = cookDefault(pstate, colDef->raw_default,
+ atp->atttypid, atp->atttypmod,
+ NameStr(atp->attname),
+ atp->attgenerated);
+
+ /*
+ * If the expression is just a NULL constant, we do not bother to make
+ * an explicit pg_attrdef entry, since the default behavior is
+ * equivalent. This applies to column defaults, but not for
+ * generation expressions.
+ *
+ * Note a nonobvious property of this test: if the column is of a
+ * domain type, what we'll get is not a bare null Const but a
+ * CoerceToDomain expr, so we will not discard the default. This is
+ * critical because the column default needs to be retained to
+ * override any default that the domain might have.
+ */
+ if (expr == NULL ||
+ (!colDef->generated &&
+ IsA(expr, Const) &&
+ castNode(Const, expr)->constisnull))
+ continue;
+
+ /* If the DEFAULT is volatile we cannot use a missing value */
+ if (colDef->missingMode && contain_volatile_functions((Node *) expr))
+ colDef->missingMode = false;
+
+ defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal,
+ colDef->missingMode);
+
+ cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+ cooked->contype = CONSTR_DEFAULT;
+ cooked->conoid = defOid;
+ cooked->name = NULL;
+ cooked->attnum = colDef->attnum;
+ cooked->expr = expr;
+ cooked->skip_validation = false;
+ cooked->is_local = is_local;
+ cooked->inhcount = is_local ? 0 : 1;
+ cooked->is_no_inherit = false;
+ cookedConstraints = lappend(cookedConstraints, cooked);
+ }
+
+ /*
+ * Process constraint expressions.
+ */
+ numchecks = numoldchecks;
+ checknames = NIL;
+ foreach(cell, newConstraints)
+ {
+ Constraint *cdef = (Constraint *) lfirst(cell);
+ char *ccname;
+ Oid constrOid;
+
+ if (cdef->contype != CONSTR_CHECK)
+ continue;
+
+ if (cdef->raw_expr != NULL)
+ {
+ Assert(cdef->cooked_expr == NULL);
+
+ /*
+ * Transform raw parsetree to executable expression, and verify
+ * it's valid as a CHECK constraint.
+ */
+ expr = cookConstraint(pstate, cdef->raw_expr,
+ RelationGetRelationName(rel));
+ }
+ else
+ {
+ Assert(cdef->cooked_expr != NULL);
+
+ /*
+ * Here, we assume the parser will only pass us valid CHECK
+ * expressions, so we do no particular checking.
+ */
+ expr = stringToNode(cdef->cooked_expr);
+ }
+
+ /*
+ * Check name uniqueness, or generate a name if none was given.
+ */
+ if (cdef->conname != NULL)
+ {
+ ListCell *cell2;
+
+ ccname = cdef->conname;
+ /* Check against other new constraints */
+ /* Needed because we don't do CommandCounterIncrement in loop */
+ foreach(cell2, checknames)
+ {
+ if (strcmp((char *) lfirst(cell2), ccname) == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("check constraint \"%s\" already exists",
+ ccname)));
+ }
+
+ /* save name for future checks */
+ checknames = lappend(checknames, ccname);
+
+ /*
+ * Check against pre-existing constraints. If we are allowed to
+ * merge with an existing constraint, there's no more to do here.
+ * (We omit the duplicate constraint from the result, which is
+ * what ATAddCheckConstraint wants.)
+ */
+ if (MergeWithExistingConstraint(rel, ccname, expr,
+ allow_merge, is_local,
+ cdef->initially_valid,
+ cdef->is_no_inherit))
+ continue;
+ }
+ else
+ {
+ /*
+ * When generating a name, we want to create "tab_col_check" for a
+ * column constraint and "tab_check" for a table constraint. We
+ * no longer have any info about the syntactic positioning of the
+ * constraint phrase, so we approximate this by seeing whether the
+ * expression references more than one column. (If the user
+ * played by the rules, the result is the same...)
+ *
+ * Note: pull_var_clause() doesn't descend into sublinks, but we
+ * eliminated those above; and anyway this only needs to be an
+ * approximate answer.
+ */
+ List *vars;
+ char *colname;
+
+ vars = pull_var_clause(expr, 0);
+
+ /* eliminate duplicates */
+ vars = list_union(NIL, vars);
+
+ if (list_length(vars) == 1)
+ colname = get_attname(RelationGetRelid(rel),
+ ((Var *) linitial(vars))->varattno,
+ true);
+ else
+ colname = NULL;
+
+ ccname = ChooseConstraintName(RelationGetRelationName(rel),
+ colname,
+ "check",
+ RelationGetNamespace(rel),
+ checknames);
+
+ /* save name for future checks */
+ checknames = lappend(checknames, ccname);
+ }
+
+ /*
+ * OK, store it.
+ */
+ constrOid =
+ StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
+ is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
+
+ numchecks++;
+
+ cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
+ cooked->contype = CONSTR_CHECK;
+ cooked->conoid = constrOid;
+ cooked->name = ccname;
+ cooked->attnum = 0;
+ cooked->expr = expr;
+ cooked->skip_validation = cdef->skip_validation;
+ cooked->is_local = is_local;
+ cooked->inhcount = is_local ? 0 : 1;
+ cooked->is_no_inherit = cdef->is_no_inherit;
+ cookedConstraints = lappend(cookedConstraints, cooked);
+ }
+
+ /*
+ * Update the count of constraints in the relation's pg_class tuple. We do
+ * this even if there was no change, in order to ensure that an SI update
+ * message is sent out for the pg_class tuple, which will force other
+ * backends to rebuild their relcache entries for the rel. (This is
+ * critical if we added defaults but not constraints.)
+ */
+ SetRelationNumChecks(rel, numchecks);
+
+ return cookedConstraints;
+}
+
+/*
+ * Check for a pre-existing check constraint that conflicts with a proposed
+ * new one, and either adjust its conislocal/coninhcount settings or throw
+ * error as needed.
+ *
+ * Returns true if merged (constraint is a duplicate), or false if it's
+ * got a so-far-unique name, or throws error if conflict.
+ *
+ * XXX See MergeConstraintsIntoExisting too if you change this code.
+ */
+static bool
+MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
+ bool allow_merge, bool is_local,
+ bool is_initially_valid,
+ bool is_no_inherit)
+{
+ bool found;
+ Relation conDesc;
+ SysScanDesc conscan;
+ ScanKeyData skey[3];
+ HeapTuple tup;
+
+ /* Search for a pg_constraint entry with same name and relation */
+ conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
+
+ found = false;
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationGetRelid(rel)));
+ ScanKeyInit(&skey[1],
+ Anum_pg_constraint_contypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(InvalidOid));
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(ccname));
+
+ conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId, true,
+ NULL, 3, skey);
+
+ /* There can be at most one matching row */
+ if (HeapTupleIsValid(tup = systable_getnext(conscan)))
+ {
+ Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);
+
+ /* Found it. Conflicts if not identical check constraint */
+ if (con->contype == CONSTRAINT_CHECK)
+ {
+ Datum val;
+ bool isnull;
+
+ val = fastgetattr(tup,
+ Anum_pg_constraint_conbin,
+ conDesc->rd_att, &isnull);
+ if (isnull)
+ elog(ERROR, "null conbin for rel %s",
+ RelationGetRelationName(rel));
+ if (equal(expr, stringToNode(TextDatumGetCString(val))))
+ found = true;
+ }
+
+ /*
+ * If the existing constraint is purely inherited (no local
+ * definition) then interpret addition of a local constraint as a
+ * legal merge. This allows ALTER ADD CONSTRAINT on parent and child
+ * tables to be given in either order with same end state. However if
+ * the relation is a partition, all inherited constraints are always
+ * non-local, including those that were merged.
+ */
+ if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
+ allow_merge = true;
+
+ if (!found || !allow_merge)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("constraint \"%s\" for relation \"%s\" already exists",
+ ccname, RelationGetRelationName(rel))));
+
+ /* If the child constraint is "no inherit" then cannot merge */
+ if (con->connoinherit)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
+ ccname, RelationGetRelationName(rel))));
+
+ /*
+ * Must not change an existing inherited constraint to "no inherit"
+ * status. That's because inherited constraints should be able to
+ * propagate to lower-level children.
+ */
+ if (con->coninhcount > 0 && is_no_inherit)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
+ ccname, RelationGetRelationName(rel))));
+
+ /*
+ * If the child constraint is "not valid" then cannot merge with a
+ * valid parent constraint.
+ */
+ if (is_initially_valid && !con->convalidated)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
+ ccname, RelationGetRelationName(rel))));
+
+ /* OK to update the tuple */
+ ereport(NOTICE,
+ (errmsg("merging constraint \"%s\" with inherited definition",
+ ccname)));
+
+ tup = heap_copytuple(tup);
+ con = (Form_pg_constraint) GETSTRUCT(tup);
+
+ /*
+ * In case of partitions, an inherited constraint must be inherited
+ * only once since it cannot have multiple parents and it is never
+ * considered local.
+ */
+ if (rel->rd_rel->relispartition)
+ {
+ con->coninhcount = 1;
+ con->conislocal = false;
+ }
+ else
+ {
+ if (is_local)
+ con->conislocal = true;
+ else
+ con->coninhcount++;
+ }
+
+ if (is_no_inherit)
+ {
+ Assert(is_local);
+ con->connoinherit = true;
+ }
+
+ CatalogTupleUpdate(conDesc, &tup->t_self, tup);
+ }
+
+ systable_endscan(conscan);
+ table_close(conDesc, RowExclusiveLock);
+
+ return found;
+}
+
+/*
+ * Update the count of constraints in the relation's pg_class tuple.
+ *
+ * Caller had better hold exclusive lock on the relation.
+ *
+ * An important side effect is that a SI update message will be sent out for
+ * the pg_class tuple, which will force other backends to rebuild their
+ * relcache entries for the rel. Also, this backend will rebuild its
+ * own relcache entry at the next CommandCounterIncrement.
+ */
+static void
+SetRelationNumChecks(Relation rel, int numchecks)
+{
+ Relation relrel;
+ HeapTuple reltup;
+ Form_pg_class relStruct;
+
+ relrel = table_open(RelationRelationId, RowExclusiveLock);
+ reltup = SearchSysCacheCopy1(RELOID,
+ ObjectIdGetDatum(RelationGetRelid(rel)));
+ if (!HeapTupleIsValid(reltup))
+ elog(ERROR, "cache lookup failed for relation %u",
+ RelationGetRelid(rel));
+ relStruct = (Form_pg_class) GETSTRUCT(reltup);
+
+ if (relStruct->relchecks != numchecks)
+ {
+ relStruct->relchecks = numchecks;
+
+ CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
+ }
+ else
+ {
+ /* Skip the disk update, but force relcache inval anyway */
+ CacheInvalidateRelcache(rel);
+ }
+
+ heap_freetuple(reltup);
+ table_close(relrel, RowExclusiveLock);
+}
+
+/*
+ * Check for references to generated columns
+ */
+static bool
+check_nested_generated_walker(Node *node, void *context)
+{
+ ParseState *pstate = context;
+
+ if (node == NULL)
+ return false;
+ else if (IsA(node, Var))
+ {
+ Var *var = (Var *) node;
+ Oid relid;
+ AttrNumber attnum;
+
+ relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
+ if (!OidIsValid(relid))
+ return false; /* XXX shouldn't we raise an error? */
+
+ attnum = var->varattno;
+
+ if (attnum > 0 && get_attgenerated(relid, attnum))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot use generated column \"%s\" in column generation expression",
+ get_attname(relid, attnum, false)),
+ errdetail("A generated column cannot reference another generated column."),
+ parser_errposition(pstate, var->location)));
+ /* A whole-row Var is necessarily self-referential, so forbid it */
+ if (attnum == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot use whole-row variable in column generation expression"),
+ errdetail("This would cause the generated column to depend on its own value."),
+ parser_errposition(pstate, var->location)));
+ /* System columns were already checked in the parser */
+
+ return false;
+ }
+ else
+ return expression_tree_walker(node, check_nested_generated_walker,
+ (void *) context);
+}
+
+static void
+check_nested_generated(ParseState *pstate, Node *node)
+{
+ check_nested_generated_walker(node, pstate);
+}
+
+/*
+ * Take a raw default and convert it to a cooked format ready for
+ * storage.
+ *
+ * Parse state should be set up to recognize any vars that might appear
+ * in the expression. (Even though we plan to reject vars, it's more
+ * user-friendly to give the correct error message than "unknown var".)
+ *
+ * If atttypid is not InvalidOid, coerce the expression to the specified
+ * type (and typmod atttypmod). attname is only needed in this case:
+ * it is used in the error message, if any.
+ */
+Node *
+cookDefault(ParseState *pstate,
+ Node *raw_default,
+ Oid atttypid,
+ int32 atttypmod,
+ const char *attname,
+ char attgenerated)
+{
+ Node *expr;
+
+ Assert(raw_default != NULL);
+
+ /*
+ * Transform raw parsetree to executable expression.
+ */
+ expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
+
+ if (attgenerated)
+ {
+ check_nested_generated(pstate, expr);
+
+ if (contain_mutable_functions(expr))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("generation expression is not immutable")));
+ }
+ else
+ {
+ /*
+ * For a default expression, transformExpr() should have rejected
+ * column references.
+ */
+ Assert(!contain_var_clause(expr));
+ }
+
+ /*
+ * Coerce the expression to the correct type and typmod, if given. This
+ * should match the parser's processing of non-defaulted expressions ---
+ * see transformAssignedExpr().
+ */
+ if (OidIsValid(atttypid))
+ {
+ Oid type_id = exprType(expr);
+
+ expr = coerce_to_target_type(pstate, expr, type_id,
+ atttypid, atttypmod,
+ COERCION_ASSIGNMENT,
+ COERCE_IMPLICIT_CAST,
+ -1);
+ if (expr == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("column \"%s\" is of type %s"
+ " but default expression is of type %s",
+ attname,
+ format_type_be(atttypid),
+ format_type_be(type_id)),
+ errhint("You will need to rewrite or cast the expression.")));
+ }
+
+ /*
+ * Finally, take care of collations in the finished expression.
+ */
+ assign_expr_collations(pstate, expr);
+
+ return expr;
+}
+
+/*
+ * Take a raw CHECK constraint expression and convert it to a cooked format
+ * ready for storage.
+ *
+ * Parse state must be set up to recognize any vars that might appear
+ * in the expression.
+ */
+static Node *
+cookConstraint(ParseState *pstate,
+ Node *raw_constraint,
+ char *relname)
+{
+ Node *expr;
+
+ /*
+ * Transform raw parsetree to executable expression.
+ */
+ expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
+
+ /*
+ * Make sure it yields a boolean result.
+ */
+ expr = coerce_to_boolean(pstate, expr, "CHECK");
+
+ /*
+ * Take care of collations.
+ */
+ assign_expr_collations(pstate, expr);
+
+ /*
+ * Make sure no outside relations are referred to (this is probably dead
+ * code now that add_missing_from is history).
+ */
+ if (list_length(pstate->p_rtable) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
+ errmsg("only table \"%s\" can be referenced in check constraint",
+ relname)));
+
+ return expr;
+}
+
+/*
+ * CopyStatistics --- copy entries in pg_statistic from one rel to another
+ */
+void
+CopyStatistics(Oid fromrelid, Oid torelid)
+{
+ HeapTuple tup;
+ SysScanDesc scan;
+ ScanKeyData key[1];
+ Relation statrel;
+
+ statrel = table_open(StatisticRelationId, RowExclusiveLock);
+
+ /* Now search for stat records */
+ ScanKeyInit(&key[0],
+ Anum_pg_statistic_starelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(fromrelid));
+
+ scan = systable_beginscan(statrel, StatisticRelidAttnumInhIndexId,
+ true, NULL, 1, key);
+
+ while (HeapTupleIsValid((tup = systable_getnext(scan))))
+ {
+ Form_pg_statistic statform;
+
+ /* make a modifiable copy */
+ tup = heap_copytuple(tup);
+ statform = (Form_pg_statistic) GETSTRUCT(tup);
+
+ /* update the copy of the tuple and insert it */
+ statform->starelid = torelid;
+ CatalogTupleInsert(statrel, tup);
+
+ heap_freetuple(tup);
+ }
+
+ systable_endscan(scan);
+
+ table_close(statrel, RowExclusiveLock);
+}
+
+/*
+ * RemoveStatistics --- remove entries in pg_statistic for a rel or column
+ *
+ * If attnum is zero, remove all entries for rel; else remove only the one(s)
+ * for that column.
+ */
+void
+RemoveStatistics(Oid relid, AttrNumber attnum)
+{
+ Relation pgstatistic;
+ SysScanDesc scan;
+ ScanKeyData key[2];
+ int nkeys;
+ HeapTuple tuple;
+
+ pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_statistic_starelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+
+ if (attnum == 0)
+ nkeys = 1;
+ else
+ {
+ ScanKeyInit(&key[1],
+ Anum_pg_statistic_staattnum,
+ BTEqualStrategyNumber, F_INT2EQ,
+ Int16GetDatum(attnum));
+ nkeys = 2;
+ }
+
+ scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
+ NULL, nkeys, key);
+
+ /* we must loop even when attnum != 0, in case of inherited stats */
+ while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ CatalogTupleDelete(pgstatistic, &tuple->t_self);
+
+ systable_endscan(scan);
+
+ table_close(pgstatistic, RowExclusiveLock);
+}
+
+
+/*
+ * RelationTruncateIndexes - truncate all indexes associated
+ * with the heap relation to zero tuples.
+ *
+ * The routine will truncate and then reconstruct the indexes on
+ * the specified relation. Caller must hold exclusive lock on rel.
+ */
+static void
+RelationTruncateIndexes(Relation heapRelation)
+{
+ ListCell *indlist;
+
+ /* Ask the relcache to produce a list of the indexes of the rel */
+ foreach(indlist, RelationGetIndexList(heapRelation))
+ {
+ Oid indexId = lfirst_oid(indlist);
+ Relation currentIndex;
+ IndexInfo *indexInfo;
+
+ /* Open the index relation; use exclusive lock, just to be sure */
+ currentIndex = index_open(indexId, AccessExclusiveLock);
+
+ /*
+ * Fetch info needed for index_build. Since we know there are no
+ * tuples that actually need indexing, we can use a dummy IndexInfo.
+ * This is slightly cheaper to build, but the real point is to avoid
+ * possibly running user-defined code in index expressions or
+ * predicates. We might be getting invoked during ON COMMIT
+ * processing, and we don't want to run any such code then.
+ */
+ indexInfo = BuildDummyIndexInfo(currentIndex);
+
+ /*
+ * Now truncate the actual file (and discard buffers).
+ */
+ RelationTruncate(currentIndex, 0);
+
+ /* Initialize the index and rebuild */
+ /* Note: we do not need to re-establish pkey setting */
+ index_build(heapRelation, currentIndex, indexInfo, true, false);
+
+ /* We're done with this index */
+ index_close(currentIndex, NoLock);
+ }
+}
+
+/*
+ * heap_truncate
+ *
+ * This routine deletes all data within all the specified relations.
+ *
+ * This is not transaction-safe! There is another, transaction-safe
+ * implementation in commands/tablecmds.c. We now use this only for
+ * ON COMMIT truncation of temporary tables, where it doesn't matter.
+ */
+void
+heap_truncate(List *relids)
+{
+ List *relations = NIL;
+ ListCell *cell;
+
+ /* Open relations for processing, and grab exclusive access on each */
+ foreach(cell, relids)
+ {
+ Oid rid = lfirst_oid(cell);
+ Relation rel;
+
+ rel = table_open(rid, AccessExclusiveLock);
+ relations = lappend(relations, rel);
+ }
+
+ /* Don't allow truncate on tables that are referenced by foreign keys */
+ heap_truncate_check_FKs(relations, true);
+
+ /* OK to do it */
+ foreach(cell, relations)
+ {
+ Relation rel = lfirst(cell);
+
+ /* Truncate the relation */
+ heap_truncate_one_rel(rel);
+
+ /* Close the relation, but keep exclusive lock on it until commit */
+ table_close(rel, NoLock);
+ }
+}
+
+/*
+ * heap_truncate_one_rel
+ *
+ * This routine deletes all data within the specified relation.
+ *
+ * This is not transaction-safe, because the truncation is done immediately
+ * and cannot be rolled back later. Caller is responsible for having
+ * checked permissions etc, and must have obtained AccessExclusiveLock.
+ */
+void
+heap_truncate_one_rel(Relation rel)
+{
+ Oid toastrelid;
+
+ /*
+ * Truncate the relation. Partitioned tables have no storage, so there is
+ * nothing to do for them here.
+ */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ return;
+
+ /* Truncate the underlying relation */
+ table_relation_nontransactional_truncate(rel);
+
+ /* If the relation has indexes, truncate the indexes too */
+ RelationTruncateIndexes(rel);
+
+ /* If there is a toast table, truncate that too */
+ toastrelid = rel->rd_rel->reltoastrelid;
+ if (OidIsValid(toastrelid))
+ {
+ Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
+
+ table_relation_nontransactional_truncate(toastrel);
+ RelationTruncateIndexes(toastrel);
+ /* keep the lock... */
+ table_close(toastrel, NoLock);
+ }
+}
+
+/*
+ * heap_truncate_check_FKs
+ * Check for foreign keys referencing a list of relations that
+ * are to be truncated, and raise error if there are any
+ *
+ * We disallow such FKs (except self-referential ones) since the whole point
+ * of TRUNCATE is to not scan the individual rows to be thrown away.
+ *
+ * This is split out so it can be shared by both implementations of truncate.
+ * Caller should already hold a suitable lock on the relations.
+ *
+ * tempTables is only used to select an appropriate error message.
+ */
+void
+heap_truncate_check_FKs(List *relations, bool tempTables)
+{
+ List *oids = NIL;
+ List *dependents;
+ ListCell *cell;
+
+ /*
+ * Build a list of OIDs of the interesting relations.
+ *
+ * If a relation has no triggers, then it can neither have FKs nor be
+ * referenced by a FK from another table, so we can ignore it. For
+ * partitioned tables, FKs have no triggers, so we must include them
+ * anyway.
+ */
+ foreach(cell, relations)
+ {
+ Relation rel = lfirst(cell);
+
+ if (rel->rd_rel->relhastriggers ||
+ rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ oids = lappend_oid(oids, RelationGetRelid(rel));
+ }
+
+ /*
+ * Fast path: if no relation has triggers, none has FKs either.
+ */
+ if (oids == NIL)
+ return;
+
+ /*
+ * Otherwise, must scan pg_constraint. We make one pass with all the
+ * relations considered; if this finds nothing, then all is well.
+ */
+ dependents = heap_truncate_find_FKs(oids);
+ if (dependents == NIL)
+ return;
+
+ /*
+ * Otherwise we repeat the scan once per relation to identify a particular
+ * pair of relations to complain about. This is pretty slow, but
+ * performance shouldn't matter much in a failure path. The reason for
+ * doing things this way is to ensure that the message produced is not
+ * dependent on chance row locations within pg_constraint.
+ */
+ foreach(cell, oids)
+ {
+ Oid relid = lfirst_oid(cell);
+ ListCell *cell2;
+
+ dependents = heap_truncate_find_FKs(list_make1_oid(relid));
+
+ foreach(cell2, dependents)
+ {
+ Oid relid2 = lfirst_oid(cell2);
+
+ if (!list_member_oid(oids, relid2))
+ {
+ char *relname = get_rel_name(relid);
+ char *relname2 = get_rel_name(relid2);
+
+ if (tempTables)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("unsupported ON COMMIT and foreign key combination"),
+ errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
+ relname2, relname)));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot truncate a table referenced in a foreign key constraint"),
+ errdetail("Table \"%s\" references \"%s\".",
+ relname2, relname),
+ errhint("Truncate table \"%s\" at the same time, "
+ "or use TRUNCATE ... CASCADE.",
+ relname2)));
+ }
+ }
+ }
+}
+
+/*
+ * heap_truncate_find_FKs
+ * Find relations having foreign keys referencing any of the given rels
+ *
+ * Input and result are both lists of relation OIDs. The result contains
+ * no duplicates, does *not* include any rels that were already in the input
+ * list, and is sorted in OID order. (The last property is enforced mainly
+ * to guarantee consistent behavior in the regression tests; we don't want
+ * behavior to change depending on chance locations of rows in pg_constraint.)
+ *
+ * Note: caller should already have appropriate lock on all rels mentioned
+ * in relationIds. Since adding or dropping an FK requires exclusive lock
+ * on both rels, this ensures that the answer will be stable.
+ */
+List *
+heap_truncate_find_FKs(List *relationIds)
+{
+ List *result = NIL;
+ List *oids = list_copy(relationIds);
+ List *parent_cons;
+ ListCell *cell;
+ ScanKeyData key;
+ Relation fkeyRel;
+ SysScanDesc fkeyScan;
+ HeapTuple tuple;
+ bool restart;
+
+ oids = list_copy(relationIds);
+
+ /*
+ * Must scan pg_constraint. Right now, it is a seqscan because there is
+ * no available index on confrelid.
+ */
+ fkeyRel = table_open(ConstraintRelationId, AccessShareLock);
+
+restart:
+ restart = false;
+ parent_cons = NIL;
+
+ fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
+ NULL, 0, NULL);
+
+ while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
+ {
+ Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
+
+ /* Not a foreign key */
+ if (con->contype != CONSTRAINT_FOREIGN)
+ continue;
+
+ /* Not referencing one of our list of tables */
+ if (!list_member_oid(oids, con->confrelid))
+ continue;
+
+ /*
+ * If this constraint has a parent constraint which we have not seen
+ * yet, keep track of it for the second loop, below. Tracking parent
+ * constraints allows us to climb up to the top-level level constraint
+ * and look for all possible relations referencing the partitioned
+ * table.
+ */
+ if (OidIsValid(con->conparentid) &&
+ !list_member_oid(parent_cons, con->conparentid))
+ parent_cons = lappend_oid(parent_cons, con->conparentid);
+
+ /*
+ * Add referencer to result, unless present in input list. (Don't
+ * worry about dupes: we'll fix that below).
+ */
+ if (!list_member_oid(relationIds, con->conrelid))
+ result = lappend_oid(result, con->conrelid);
+ }
+
+ systable_endscan(fkeyScan);
+
+ /*
+ * Process each parent constraint we found to add the list of referenced
+ * relations by them to the oids list. If we do add any new such
+ * relations, redo the first loop above. Also, if we see that the parent
+ * constraint in turn has a parent, add that so that we process all
+ * relations in a single additional pass.
+ */
+ foreach(cell, parent_cons)
+ {
+ Oid parent = lfirst_oid(cell);
+
+ ScanKeyInit(&key,
+ Anum_pg_constraint_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(parent));
+
+ fkeyScan = systable_beginscan(fkeyRel, ConstraintOidIndexId,
+ true, NULL, 1, &key);
+
+ tuple = systable_getnext(fkeyScan);
+ if (HeapTupleIsValid(tuple))
+ {
+ Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
+
+ /*
+ * pg_constraint rows always appear for partitioned hierarchies
+ * this way: on the each side of the constraint, one row appears
+ * for each partition that points to the top-most table on the
+ * other side.
+ *
+ * Because of this arrangement, we can correctly catch all
+ * relevant relations by adding to 'parent_cons' all rows with
+ * valid conparentid, and to the 'oids' list all rows with a zero
+ * conparentid. If any oids are added to 'oids', redo the first
+ * loop above by setting 'restart'.
+ */
+ if (OidIsValid(con->conparentid))
+ parent_cons = list_append_unique_oid(parent_cons,
+ con->conparentid);
+ else if (!list_member_oid(oids, con->confrelid))
+ {
+ oids = lappend_oid(oids, con->confrelid);
+ restart = true;
+ }
+ }
+
+ systable_endscan(fkeyScan);
+ }
+
+ list_free(parent_cons);
+ if (restart)
+ goto restart;
+
+ table_close(fkeyRel, AccessShareLock);
+ list_free(oids);
+
+ /* Now sort and de-duplicate the result list */
+ list_sort(result, list_oid_cmp);
+ list_deduplicate_oid(result);
+
+ return result;
+}
+
+/*
+ * StorePartitionKey
+ * Store information about the partition key rel into the catalog
+ */
+void
+StorePartitionKey(Relation rel,
+ char strategy,
+ int16 partnatts,
+ AttrNumber *partattrs,
+ List *partexprs,
+ Oid *partopclass,
+ Oid *partcollation)
+{
+ int i;
+ int2vector *partattrs_vec;
+ oidvector *partopclass_vec;
+ oidvector *partcollation_vec;
+ Datum partexprDatum;
+ Relation pg_partitioned_table;
+ HeapTuple tuple;
+ Datum values[Natts_pg_partitioned_table];
+ bool nulls[Natts_pg_partitioned_table];
+ ObjectAddress myself;
+ ObjectAddress referenced;
+
+ Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
+
+ /* Copy the partition attribute numbers, opclass OIDs into arrays */
+ partattrs_vec = buildint2vector(partattrs, partnatts);
+ partopclass_vec = buildoidvector(partopclass, partnatts);
+ partcollation_vec = buildoidvector(partcollation, partnatts);
+
+ /* Convert the expressions (if any) to a text datum */
+ if (partexprs)
+ {
+ char *exprString;
+
+ exprString = nodeToString(partexprs);
+ partexprDatum = CStringGetTextDatum(exprString);
+ pfree(exprString);
+ }
+ else
+ partexprDatum = (Datum) 0;
+
+ pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
+
+ MemSet(nulls, false, sizeof(nulls));
+
+ /* Only this can ever be NULL */
+ if (!partexprDatum)
+ nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
+
+ values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
+ values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
+ values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
+ values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
+ values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
+ values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
+ values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
+
+ tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
+
+ CatalogTupleInsert(pg_partitioned_table, tuple);
+ table_close(pg_partitioned_table, RowExclusiveLock);
+
+ /* Mark this relation as dependent on a few things as follows */
+ myself.classId = RelationRelationId;
+ myself.objectId = RelationGetRelid(rel);
+ myself.objectSubId = 0;
+
+ /* Operator class and collation per key column */
+ for (i = 0; i < partnatts; i++)
+ {
+ referenced.classId = OperatorClassRelationId;
+ referenced.objectId = partopclass[i];
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* The default collation is pinned, so don't bother recording it */
+ if (OidIsValid(partcollation[i]) &&
+ partcollation[i] != DEFAULT_COLLATION_OID)
+ {
+ referenced.classId = CollationRelationId;
+ referenced.objectId = partcollation[i];
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+ }
+
+ /*
+ * The partitioning columns are made internally dependent on the table,
+ * because we cannot drop any of them without dropping the whole table.
+ * (ATExecDropColumn independently enforces that, but it's not bulletproof
+ * so we need the dependencies too.)
+ */
+ for (i = 0; i < partnatts; i++)
+ {
+ if (partattrs[i] == 0)
+ continue; /* ignore expressions here */
+
+ referenced.classId = RelationRelationId;
+ referenced.objectId = RelationGetRelid(rel);
+ referenced.objectSubId = partattrs[i];
+
+ recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
+ }
+
+ /*
+ * Also consider anything mentioned in partition expressions. External
+ * references (e.g. functions) get NORMAL dependencies. Table columns
+ * mentioned in the expressions are handled the same as plain partitioning
+ * columns, i.e. they become internally dependent on the whole table.
+ */
+ if (partexprs)
+ recordDependencyOnSingleRelExpr(&myself,
+ (Node *) partexprs,
+ RelationGetRelid(rel),
+ DEPENDENCY_NORMAL,
+ DEPENDENCY_INTERNAL,
+ true /* reverse the self-deps */ );
+
+ /*
+ * We must invalidate the relcache so that the next
+ * CommandCounterIncrement() will cause the same to be rebuilt using the
+ * information in just created catalog entry.
+ */
+ CacheInvalidateRelcache(rel);
+}
+
+/*
+ * RemovePartitionKeyByRelId
+ * Remove pg_partitioned_table entry for a relation
+ */
+void
+RemovePartitionKeyByRelId(Oid relid)
+{
+ Relation rel;
+ HeapTuple tuple;
+
+ rel = table_open(PartitionedRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for partition key of relation %u",
+ relid);
+
+ CatalogTupleDelete(rel, &tuple->t_self);
+
+ ReleaseSysCache(tuple);
+ table_close(rel, RowExclusiveLock);
+}
+
+/*
+ * StorePartitionBound
+ * Update pg_class tuple of rel to store the partition bound and set
+ * relispartition to true
+ *
+ * If this is the default partition, also update the default partition OID in
+ * pg_partitioned_table.
+ *
+ * Also, invalidate the parent's relcache, so that the next rebuild will load
+ * the new partition's info into its partition descriptor. If there is a
+ * default partition, we must invalidate its relcache entry as well.
+ */
+void
+StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound)
+{
+ Relation classRel;
+ HeapTuple tuple,
+ newtuple;
+ Datum new_val[Natts_pg_class];
+ bool new_null[Natts_pg_class],
+ new_repl[Natts_pg_class];
+ Oid defaultPartOid;
+
+ /* Update pg_class tuple */
+ classRel = table_open(RelationRelationId, RowExclusiveLock);
+ tuple = SearchSysCacheCopy1(RELOID,
+ ObjectIdGetDatum(RelationGetRelid(rel)));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u",
+ RelationGetRelid(rel));
+
+#ifdef USE_ASSERT_CHECKING
+ {
+ Form_pg_class classForm;
+ bool isnull;
+
+ classForm = (Form_pg_class) GETSTRUCT(tuple);
+ Assert(!classForm->relispartition);
+ (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
+ &isnull);
+ Assert(isnull);
+ }
+#endif
+
+ /* Fill in relpartbound value */
+ memset(new_val, 0, sizeof(new_val));
+ memset(new_null, false, sizeof(new_null));
+ memset(new_repl, false, sizeof(new_repl));
+ new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
+ new_null[Anum_pg_class_relpartbound - 1] = false;
+ new_repl[Anum_pg_class_relpartbound - 1] = true;
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
+ new_val, new_null, new_repl);
+ /* Also set the flag */
+ ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
+ CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
+ heap_freetuple(newtuple);
+ table_close(classRel, RowExclusiveLock);
+
+ /*
+ * If we're storing bounds for the default partition, update
+ * pg_partitioned_table too.
+ */
+ if (bound->is_default)
+ update_default_partition_oid(RelationGetRelid(parent),
+ RelationGetRelid(rel));
+
+ /* Make these updates visible */
+ CommandCounterIncrement();
+
+ /*
+ * The partition constraint for the default partition depends on the
+ * partition bounds of every other partition, so we must invalidate the
+ * relcache entry for that partition every time a partition is added or
+ * removed.
+ */
+ defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
+ if (OidIsValid(defaultPartOid))
+ CacheInvalidateRelcacheByRelid(defaultPartOid);
+
+ CacheInvalidateRelcache(parent);
+}
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
new file mode 100644
index 0000000..852b948
--- /dev/null
+++ b/src/backend/catalog/index.c
@@ -0,0 +1,4034 @@
+/*-------------------------------------------------------------------------
+ *
+ * index.c
+ * code to create and destroy POSTGRES index relations
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/index.c
+ *
+ *
+ * INTERFACE ROUTINES
+ * index_create() - Create a cataloged index relation
+ * index_drop() - Removes index relation from catalogs
+ * BuildIndexInfo() - Prepare to insert index tuples
+ * FormIndexDatum() - Construct datum vector for one index tuple
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <unistd.h>
+
+#include "access/amapi.h"
+#include "access/heapam.h"
+#include "access/multixact.h"
+#include "access/reloptions.h"
+#include "access/relscan.h"
+#include "access/sysattr.h"
+#include "access/tableam.h"
+#include "access/transam.h"
+#include "access/visibilitymap.h"
+#include "access/xact.h"
+#include "bootstrap/bootstrap.h"
+#include "catalog/binary_upgrade.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/heap.h"
+#include "catalog/index.h"
+#include "catalog/objectaccess.h"
+#include "catalog/partition.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_constraint.h"
+#include "catalog/pg_depend.h"
+#include "catalog/pg_description.h"
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_tablespace.h"
+#include "catalog/pg_trigger.h"
+#include "catalog/pg_type.h"
+#include "catalog/storage.h"
+#include "commands/event_trigger.h"
+#include "commands/progress.h"
+#include "commands/tablecmds.h"
+#include "commands/trigger.h"
+#include "executor/executor.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
+#include "optimizer/optimizer.h"
+#include "parser/parser.h"
+#include "pgstat.h"
+#include "rewrite/rewriteManip.h"
+#include "storage/bufmgr.h"
+#include "storage/lmgr.h"
+#include "storage/predicate.h"
+#include "storage/procarray.h"
+#include "storage/smgr.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/guc.h"
+#include "utils/inval.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/pg_rusage.h"
+#include "utils/snapmgr.h"
+#include "utils/syscache.h"
+#include "utils/tuplesort.h"
+
+/* Potentially set by pg_upgrade_support functions */
+Oid binary_upgrade_next_index_pg_class_oid = InvalidOid;
+
+/*
+ * Pointer-free representation of variables used when reindexing system
+ * catalogs; we use this to propagate those values to parallel workers.
+ */
+typedef struct
+{
+ Oid currentlyReindexedHeap;
+ Oid currentlyReindexedIndex;
+ int numPendingReindexedIndexes;
+ Oid pendingReindexedIndexes[FLEXIBLE_ARRAY_MEMBER];
+} SerializedReindexState;
+
+/* non-export function prototypes */
+static bool relationHasPrimaryKey(Relation rel);
+static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
+ IndexInfo *indexInfo,
+ List *indexColNames,
+ Oid accessMethodObjectId,
+ Oid *collationObjectId,
+ Oid *classObjectId);
+static void InitializeAttributeOids(Relation indexRelation,
+ int numatts, Oid indexoid);
+static void AppendAttributeTuples(Relation indexRelation, int numatts,
+ Datum *attopts);
+static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
+ Oid parentIndexId,
+ IndexInfo *indexInfo,
+ Oid *collationOids,
+ Oid *classOids,
+ int16 *coloptions,
+ bool primary,
+ bool isexclusion,
+ bool immediate,
+ bool isvalid,
+ bool isready);
+static void index_update_stats(Relation rel,
+ bool hasindex,
+ double reltuples);
+static void IndexCheckExclusion(Relation heapRelation,
+ Relation indexRelation,
+ IndexInfo *indexInfo);
+static bool validate_index_callback(ItemPointer itemptr, void *opaque);
+static bool ReindexIsCurrentlyProcessingIndex(Oid indexOid);
+static void SetReindexProcessing(Oid heapOid, Oid indexOid);
+static void ResetReindexProcessing(void);
+static void SetReindexPending(List *indexes);
+static void RemoveReindexPending(Oid indexOid);
+
+
+/*
+ * relationHasPrimaryKey
+ * See whether an existing relation has a primary key.
+ *
+ * Caller must have suitable lock on the relation.
+ *
+ * Note: we intentionally do not check indisvalid here; that's because this
+ * is used to enforce the rule that there can be only one indisprimary index,
+ * and we want that to be true even if said index is invalid.
+ */
+static bool
+relationHasPrimaryKey(Relation rel)
+{
+ bool result = false;
+ List *indexoidlist;
+ ListCell *indexoidscan;
+
+ /*
+ * Get the list of index OIDs for the table from the relcache, and look up
+ * each one in the pg_index syscache until we find one marked primary key
+ * (hopefully there isn't more than one such).
+ */
+ indexoidlist = RelationGetIndexList(rel);
+
+ foreach(indexoidscan, indexoidlist)
+ {
+ Oid indexoid = lfirst_oid(indexoidscan);
+ HeapTuple indexTuple;
+
+ indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
+ if (!HeapTupleIsValid(indexTuple)) /* should not happen */
+ elog(ERROR, "cache lookup failed for index %u", indexoid);
+ result = ((Form_pg_index) GETSTRUCT(indexTuple))->indisprimary;
+ ReleaseSysCache(indexTuple);
+ if (result)
+ break;
+ }
+
+ list_free(indexoidlist);
+
+ return result;
+}
+
+/*
+ * index_check_primary_key
+ * Apply special checks needed before creating a PRIMARY KEY index
+ *
+ * This processing used to be in DefineIndex(), but has been split out
+ * so that it can be applied during ALTER TABLE ADD PRIMARY KEY USING INDEX.
+ *
+ * We check for a pre-existing primary key, and that all columns of the index
+ * are simple column references (not expressions), and that all those
+ * columns are marked NOT NULL. If not, fail.
+ *
+ * We used to automatically change unmarked columns to NOT NULL here by doing
+ * our own local ALTER TABLE command. But that doesn't work well if we're
+ * executing one subcommand of an ALTER TABLE: the operations may not get
+ * performed in the right order overall. Now we expect that the parser
+ * inserted any required ALTER TABLE SET NOT NULL operations before trying
+ * to create a primary-key index.
+ *
+ * Caller had better have at least ShareLock on the table, else the not-null
+ * checking isn't trustworthy.
+ */
+void
+index_check_primary_key(Relation heapRel,
+ IndexInfo *indexInfo,
+ bool is_alter_table,
+ IndexStmt *stmt)
+{
+ int i;
+
+ /*
+ * If ALTER TABLE or CREATE TABLE .. PARTITION OF, check that there isn't
+ * already a PRIMARY KEY. In CREATE TABLE for an ordinary relation, we
+ * have faith that the parser rejected multiple pkey clauses; and CREATE
+ * INDEX doesn't have a way to say PRIMARY KEY, so it's no problem either.
+ */
+ if ((is_alter_table || heapRel->rd_rel->relispartition) &&
+ relationHasPrimaryKey(heapRel))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("multiple primary keys for table \"%s\" are not allowed",
+ RelationGetRelationName(heapRel))));
+ }
+
+ /*
+ * Check that all of the attributes in a primary key are marked as not
+ * null. (We don't really expect to see that; it'd mean the parser messed
+ * up. But it seems wise to check anyway.)
+ */
+ for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
+ {
+ AttrNumber attnum = indexInfo->ii_IndexAttrNumbers[i];
+ HeapTuple atttuple;
+ Form_pg_attribute attform;
+
+ if (attnum == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("primary keys cannot be expressions")));
+
+ /* System attributes are never null, so no need to check */
+ if (attnum < 0)
+ continue;
+
+ atttuple = SearchSysCache2(ATTNUM,
+ ObjectIdGetDatum(RelationGetRelid(heapRel)),
+ Int16GetDatum(attnum));
+ if (!HeapTupleIsValid(atttuple))
+ elog(ERROR, "cache lookup failed for attribute %d of relation %u",
+ attnum, RelationGetRelid(heapRel));
+ attform = (Form_pg_attribute) GETSTRUCT(atttuple);
+
+ if (!attform->attnotnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("primary key column \"%s\" is not marked NOT NULL",
+ NameStr(attform->attname))));
+
+ ReleaseSysCache(atttuple);
+ }
+}
+
+/*
+ * ConstructTupleDescriptor
+ *
+ * Build an index tuple descriptor for a new index
+ */
+static TupleDesc
+ConstructTupleDescriptor(Relation heapRelation,
+ IndexInfo *indexInfo,
+ List *indexColNames,
+ Oid accessMethodObjectId,
+ Oid *collationObjectId,
+ Oid *classObjectId)
+{
+ int numatts = indexInfo->ii_NumIndexAttrs;
+ int numkeyatts = indexInfo->ii_NumIndexKeyAttrs;
+ ListCell *colnames_item = list_head(indexColNames);
+ ListCell *indexpr_item = list_head(indexInfo->ii_Expressions);
+ IndexAmRoutine *amroutine;
+ TupleDesc heapTupDesc;
+ TupleDesc indexTupDesc;
+ int natts; /* #atts in heap rel --- for error checks */
+ int i;
+
+ /* We need access to the index AM's API struct */
+ amroutine = GetIndexAmRoutineByAmId(accessMethodObjectId, false);
+
+ /* ... and to the table's tuple descriptor */
+ heapTupDesc = RelationGetDescr(heapRelation);
+ natts = RelationGetForm(heapRelation)->relnatts;
+
+ /*
+ * allocate the new tuple descriptor
+ */
+ indexTupDesc = CreateTemplateTupleDesc(numatts);
+
+ /*
+ * Fill in the pg_attribute row.
+ */
+ for (i = 0; i < numatts; i++)
+ {
+ AttrNumber atnum = indexInfo->ii_IndexAttrNumbers[i];
+ Form_pg_attribute to = TupleDescAttr(indexTupDesc, i);
+ HeapTuple tuple;
+ Form_pg_type typeTup;
+ Form_pg_opclass opclassTup;
+ Oid keyType;
+
+ MemSet(to, 0, ATTRIBUTE_FIXED_PART_SIZE);
+ to->attnum = i + 1;
+ to->attstattarget = -1;
+ to->attcacheoff = -1;
+ to->attislocal = true;
+ to->attcollation = (i < numkeyatts) ?
+ collationObjectId[i] : InvalidOid;
+
+ /*
+ * Set the attribute name as specified by caller.
+ */
+ if (colnames_item == NULL) /* shouldn't happen */
+ elog(ERROR, "too few entries in colnames list");
+ namestrcpy(&to->attname, (const char *) lfirst(colnames_item));
+ colnames_item = lnext(indexColNames, colnames_item);
+
+ /*
+ * For simple index columns, we copy some pg_attribute fields from the
+ * parent relation. For expressions we have to look at the expression
+ * result.
+ */
+ if (atnum != 0)
+ {
+ /* Simple index column */
+ const FormData_pg_attribute *from;
+
+ Assert(atnum > 0); /* should've been caught above */
+
+ if (atnum > natts) /* safety check */
+ elog(ERROR, "invalid column number %d", atnum);
+ from = TupleDescAttr(heapTupDesc,
+ AttrNumberGetAttrOffset(atnum));
+
+ to->atttypid = from->atttypid;
+ to->attlen = from->attlen;
+ to->attndims = from->attndims;
+ to->atttypmod = from->atttypmod;
+ to->attbyval = from->attbyval;
+ to->attstorage = from->attstorage;
+ to->attalign = from->attalign;
+ }
+ else
+ {
+ /* Expressional index */
+ Node *indexkey;
+
+ if (indexpr_item == NULL) /* shouldn't happen */
+ elog(ERROR, "too few entries in indexprs list");
+ indexkey = (Node *) lfirst(indexpr_item);
+ indexpr_item = lnext(indexInfo->ii_Expressions, indexpr_item);
+
+ /*
+ * Lookup the expression type in pg_type for the type length etc.
+ */
+ keyType = exprType(indexkey);
+ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for type %u", keyType);
+ typeTup = (Form_pg_type) GETSTRUCT(tuple);
+
+ /*
+ * Assign some of the attributes values. Leave the rest.
+ */
+ to->atttypid = keyType;
+ to->attlen = typeTup->typlen;
+ to->attbyval = typeTup->typbyval;
+ to->attstorage = typeTup->typstorage;
+ to->attalign = typeTup->typalign;
+ to->atttypmod = exprTypmod(indexkey);
+
+ ReleaseSysCache(tuple);
+
+ /*
+ * Make sure the expression yields a type that's safe to store in
+ * an index. We need this defense because we have index opclasses
+ * for pseudo-types such as "record", and the actually stored type
+ * had better be safe; eg, a named composite type is okay, an
+ * anonymous record type is not. The test is the same as for
+ * whether a table column is of a safe type (which is why we
+ * needn't check for the non-expression case).
+ */
+ CheckAttributeType(NameStr(to->attname),
+ to->atttypid, to->attcollation,
+ NIL, 0);
+ }
+
+ /*
+ * We do not yet have the correct relation OID for the index, so just
+ * set it invalid for now. InitializeAttributeOids() will fix it
+ * later.
+ */
+ to->attrelid = InvalidOid;
+
+ /*
+ * Check the opclass and index AM to see if either provides a keytype
+ * (overriding the attribute type). Opclass (if exists) takes
+ * precedence.
+ */
+ keyType = amroutine->amkeytype;
+
+ if (i < indexInfo->ii_NumIndexKeyAttrs)
+ {
+ tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(classObjectId[i]));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for opclass %u",
+ classObjectId[i]);
+ opclassTup = (Form_pg_opclass) GETSTRUCT(tuple);
+ if (OidIsValid(opclassTup->opckeytype))
+ keyType = opclassTup->opckeytype;
+
+ /*
+ * If keytype is specified as ANYELEMENT, and opcintype is
+ * ANYARRAY, then the attribute type must be an array (else it'd
+ * not have matched this opclass); use its element type.
+ *
+ * We could also allow ANYCOMPATIBLE/ANYCOMPATIBLEARRAY here, but
+ * there seems no need to do so; there's no reason to declare an
+ * opclass as taking ANYCOMPATIBLEARRAY rather than ANYARRAY.
+ */
+ if (keyType == ANYELEMENTOID && opclassTup->opcintype == ANYARRAYOID)
+ {
+ keyType = get_base_element_type(to->atttypid);
+ if (!OidIsValid(keyType))
+ elog(ERROR, "could not get element type of array type %u",
+ to->atttypid);
+ }
+
+ ReleaseSysCache(tuple);
+ }
+
+ /*
+ * If a key type different from the heap value is specified, update
+ * the type-related fields in the index tupdesc.
+ */
+ if (OidIsValid(keyType) && keyType != to->atttypid)
+ {
+ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for type %u", keyType);
+ typeTup = (Form_pg_type) GETSTRUCT(tuple);
+
+ to->atttypid = keyType;
+ to->atttypmod = -1;
+ to->attlen = typeTup->typlen;
+ to->attbyval = typeTup->typbyval;
+ to->attalign = typeTup->typalign;
+ to->attstorage = typeTup->typstorage;
+
+ ReleaseSysCache(tuple);
+ }
+ }
+
+ pfree(amroutine);
+
+ return indexTupDesc;
+}
+
+/* ----------------------------------------------------------------
+ * InitializeAttributeOids
+ * ----------------------------------------------------------------
+ */
+static void
+InitializeAttributeOids(Relation indexRelation,
+ int numatts,
+ Oid indexoid)
+{
+ TupleDesc tupleDescriptor;
+ int i;
+
+ tupleDescriptor = RelationGetDescr(indexRelation);
+
+ for (i = 0; i < numatts; i += 1)
+ TupleDescAttr(tupleDescriptor, i)->attrelid = indexoid;
+}
+
+/* ----------------------------------------------------------------
+ * AppendAttributeTuples
+ * ----------------------------------------------------------------
+ */
+static void
+AppendAttributeTuples(Relation indexRelation, int numatts, Datum *attopts)
+{
+ Relation pg_attribute;
+ CatalogIndexState indstate;
+ TupleDesc indexTupDesc;
+ int i;
+
+ /*
+ * open the attribute relation and its indexes
+ */
+ pg_attribute = table_open(AttributeRelationId, RowExclusiveLock);
+
+ indstate = CatalogOpenIndexes(pg_attribute);
+
+ /*
+ * insert data from new index's tupdesc into pg_attribute
+ */
+ indexTupDesc = RelationGetDescr(indexRelation);
+
+ for (i = 0; i < numatts; i++)
+ {
+ Form_pg_attribute attr = TupleDescAttr(indexTupDesc, i);
+ Datum attoptions = attopts ? attopts[i] : (Datum) 0;
+
+ Assert(attr->attnum == i + 1);
+
+ InsertPgAttributeTuple(pg_attribute, attr, attoptions, indstate);
+ }
+
+ CatalogCloseIndexes(indstate);
+
+ table_close(pg_attribute, RowExclusiveLock);
+}
+
+/* ----------------------------------------------------------------
+ * UpdateIndexRelation
+ *
+ * Construct and insert a new entry in the pg_index catalog
+ * ----------------------------------------------------------------
+ */
+static void
+UpdateIndexRelation(Oid indexoid,
+ Oid heapoid,
+ Oid parentIndexId,
+ IndexInfo *indexInfo,
+ Oid *collationOids,
+ Oid *classOids,
+ int16 *coloptions,
+ bool primary,
+ bool isexclusion,
+ bool immediate,
+ bool isvalid,
+ bool isready)
+{
+ int2vector *indkey;
+ oidvector *indcollation;
+ oidvector *indclass;
+ int2vector *indoption;
+ Datum exprsDatum;
+ Datum predDatum;
+ Datum values[Natts_pg_index];
+ bool nulls[Natts_pg_index];
+ Relation pg_index;
+ HeapTuple tuple;
+ int i;
+
+ /*
+ * Copy the index key, opclass, and indoption info into arrays (should we
+ * make the caller pass them like this to start with?)
+ */
+ indkey = buildint2vector(NULL, indexInfo->ii_NumIndexAttrs);
+ for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+ indkey->values[i] = indexInfo->ii_IndexAttrNumbers[i];
+ indcollation = buildoidvector(collationOids, indexInfo->ii_NumIndexKeyAttrs);
+ indclass = buildoidvector(classOids, indexInfo->ii_NumIndexKeyAttrs);
+ indoption = buildint2vector(coloptions, indexInfo->ii_NumIndexKeyAttrs);
+
+ /*
+ * Convert the index expressions (if any) to a text datum
+ */
+ if (indexInfo->ii_Expressions != NIL)
+ {
+ char *exprsString;
+
+ exprsString = nodeToString(indexInfo->ii_Expressions);
+ exprsDatum = CStringGetTextDatum(exprsString);
+ pfree(exprsString);
+ }
+ else
+ exprsDatum = (Datum) 0;
+
+ /*
+ * Convert the index predicate (if any) to a text datum. Note we convert
+ * implicit-AND format to normal explicit-AND for storage.
+ */
+ if (indexInfo->ii_Predicate != NIL)
+ {
+ char *predString;
+
+ predString = nodeToString(make_ands_explicit(indexInfo->ii_Predicate));
+ predDatum = CStringGetTextDatum(predString);
+ pfree(predString);
+ }
+ else
+ predDatum = (Datum) 0;
+
+
+ /*
+ * open the system catalog index relation
+ */
+ pg_index = table_open(IndexRelationId, RowExclusiveLock);
+
+ /*
+ * Build a pg_index tuple
+ */
+ MemSet(nulls, false, sizeof(nulls));
+
+ values[Anum_pg_index_indexrelid - 1] = ObjectIdGetDatum(indexoid);
+ values[Anum_pg_index_indrelid - 1] = ObjectIdGetDatum(heapoid);
+ values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs);
+ values[Anum_pg_index_indnkeyatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexKeyAttrs);
+ values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique);
+ values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary);
+ values[Anum_pg_index_indisexclusion - 1] = BoolGetDatum(isexclusion);
+ values[Anum_pg_index_indimmediate - 1] = BoolGetDatum(immediate);
+ values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false);
+ values[Anum_pg_index_indisvalid - 1] = BoolGetDatum(isvalid);
+ values[Anum_pg_index_indcheckxmin - 1] = BoolGetDatum(false);
+ values[Anum_pg_index_indisready - 1] = BoolGetDatum(isready);
+ values[Anum_pg_index_indislive - 1] = BoolGetDatum(true);
+ values[Anum_pg_index_indisreplident - 1] = BoolGetDatum(false);
+ values[Anum_pg_index_indkey - 1] = PointerGetDatum(indkey);
+ values[Anum_pg_index_indcollation - 1] = PointerGetDatum(indcollation);
+ values[Anum_pg_index_indclass - 1] = PointerGetDatum(indclass);
+ values[Anum_pg_index_indoption - 1] = PointerGetDatum(indoption);
+ values[Anum_pg_index_indexprs - 1] = exprsDatum;
+ if (exprsDatum == (Datum) 0)
+ nulls[Anum_pg_index_indexprs - 1] = true;
+ values[Anum_pg_index_indpred - 1] = predDatum;
+ if (predDatum == (Datum) 0)
+ nulls[Anum_pg_index_indpred - 1] = true;
+
+ tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls);
+
+ /*
+ * insert the tuple into the pg_index catalog
+ */
+ CatalogTupleInsert(pg_index, tuple);
+
+ /*
+ * close the relation and free the tuple
+ */
+ table_close(pg_index, RowExclusiveLock);
+ heap_freetuple(tuple);
+}
+
+
+/*
+ * index_create
+ *
+ * heapRelation: table to build index on (suitably locked by caller)
+ * indexRelationName: what it say
+ * indexRelationId: normally, pass InvalidOid to let this routine
+ * generate an OID for the index. During bootstrap this may be
+ * nonzero to specify a preselected OID.
+ * parentIndexRelid: if creating an index partition, the OID of the
+ * parent index; otherwise InvalidOid.
+ * parentConstraintId: if creating a constraint on a partition, the OID
+ * of the constraint in the parent; otherwise InvalidOid.
+ * relFileNode: normally, pass InvalidOid to get new storage. May be
+ * nonzero to attach an existing valid build.
+ * indexInfo: same info executor uses to insert into the index
+ * indexColNames: column names to use for index (List of char *)
+ * accessMethodObjectId: OID of index AM to use
+ * tableSpaceId: OID of tablespace to use
+ * collationObjectId: array of collation OIDs, one per index column
+ * classObjectId: array of index opclass OIDs, one per index column
+ * coloptions: array of per-index-column indoption settings
+ * reloptions: AM-specific options
+ * flags: bitmask that can include any combination of these bits:
+ * INDEX_CREATE_IS_PRIMARY
+ * the index is a primary key
+ * INDEX_CREATE_ADD_CONSTRAINT:
+ * invoke index_constraint_create also
+ * INDEX_CREATE_SKIP_BUILD:
+ * skip the index_build() step for the moment; caller must do it
+ * later (typically via reindex_index())
+ * INDEX_CREATE_CONCURRENT:
+ * do not lock the table against writers. The index will be
+ * marked "invalid" and the caller must take additional steps
+ * to fix it up.
+ * INDEX_CREATE_IF_NOT_EXISTS:
+ * do not throw an error if a relation with the same name
+ * already exists.
+ * INDEX_CREATE_PARTITIONED:
+ * create a partitioned index (table must be partitioned)
+ * constr_flags: flags passed to index_constraint_create
+ * (only if INDEX_CREATE_ADD_CONSTRAINT is set)
+ * allow_system_table_mods: allow table to be a system catalog
+ * is_internal: if true, post creation hook for new index
+ * constraintId: if not NULL, receives OID of created constraint
+ *
+ * Returns the OID of the created index.
+ */
+Oid
+index_create(Relation heapRelation,
+ const char *indexRelationName,
+ Oid indexRelationId,
+ Oid parentIndexRelid,
+ Oid parentConstraintId,
+ Oid relFileNode,
+ IndexInfo *indexInfo,
+ List *indexColNames,
+ Oid accessMethodObjectId,
+ Oid tableSpaceId,
+ Oid *collationObjectId,
+ Oid *classObjectId,
+ int16 *coloptions,
+ Datum reloptions,
+ bits16 flags,
+ bits16 constr_flags,
+ bool allow_system_table_mods,
+ bool is_internal,
+ Oid *constraintId)
+{
+ Oid heapRelationId = RelationGetRelid(heapRelation);
+ Relation pg_class;
+ Relation indexRelation;
+ TupleDesc indexTupDesc;
+ bool shared_relation;
+ bool mapped_relation;
+ bool is_exclusion;
+ Oid namespaceId;
+ int i;
+ char relpersistence;
+ bool isprimary = (flags & INDEX_CREATE_IS_PRIMARY) != 0;
+ bool invalid = (flags & INDEX_CREATE_INVALID) != 0;
+ bool concurrent = (flags & INDEX_CREATE_CONCURRENT) != 0;
+ bool partitioned = (flags & INDEX_CREATE_PARTITIONED) != 0;
+ char relkind;
+ TransactionId relfrozenxid;
+ MultiXactId relminmxid;
+
+ /* constraint flags can only be set when a constraint is requested */
+ Assert((constr_flags == 0) ||
+ ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0));
+ /* partitioned indexes must never be "built" by themselves */
+ Assert(!partitioned || (flags & INDEX_CREATE_SKIP_BUILD));
+
+ relkind = partitioned ? RELKIND_PARTITIONED_INDEX : RELKIND_INDEX;
+ is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
+
+ pg_class = table_open(RelationRelationId, RowExclusiveLock);
+
+ /*
+ * The index will be in the same namespace as its parent table, and is
+ * shared across databases if and only if the parent is. Likewise, it
+ * will use the relfilenode map if and only if the parent does; and it
+ * inherits the parent's relpersistence.
+ */
+ namespaceId = RelationGetNamespace(heapRelation);
+ shared_relation = heapRelation->rd_rel->relisshared;
+ mapped_relation = RelationIsMapped(heapRelation);
+ relpersistence = heapRelation->rd_rel->relpersistence;
+
+ /*
+ * check parameters
+ */
+ if (indexInfo->ii_NumIndexAttrs < 1)
+ elog(ERROR, "must index at least one column");
+
+ if (!allow_system_table_mods &&
+ IsSystemRelation(heapRelation) &&
+ IsNormalProcessingMode())
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("user-defined indexes on system catalog tables are not supported")));
+
+ /*
+ * Btree text_pattern_ops uses text_eq as the equality operator, which is
+ * fine as long as the collation is deterministic; text_eq then reduces to
+ * bitwise equality and so it is semantically compatible with the other
+ * operators and functions in that opclass. But with a nondeterministic
+ * collation, text_eq could yield results that are incompatible with the
+ * actual behavior of the index (which is determined by the opclass's
+ * comparison function). We prevent such problems by refusing creation of
+ * an index with that opclass and a nondeterministic collation.
+ *
+ * The same applies to varchar_pattern_ops and bpchar_pattern_ops. If we
+ * find more cases, we might decide to create a real mechanism for marking
+ * opclasses as incompatible with nondeterminism; but for now, this small
+ * hack suffices.
+ *
+ * Another solution is to use a special operator, not text_eq, as the
+ * equality opclass member; but that is undesirable because it would
+ * prevent index usage in many queries that work fine today.
+ */
+ for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
+ {
+ Oid collation = collationObjectId[i];
+ Oid opclass = classObjectId[i];
+
+ if (collation)
+ {
+ if ((opclass == TEXT_BTREE_PATTERN_OPS_OID ||
+ opclass == VARCHAR_BTREE_PATTERN_OPS_OID ||
+ opclass == BPCHAR_BTREE_PATTERN_OPS_OID) &&
+ !get_collation_isdeterministic(collation))
+ {
+ HeapTuple classtup;
+
+ classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
+ if (!HeapTupleIsValid(classtup))
+ elog(ERROR, "cache lookup failed for operator class %u", opclass);
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("nondeterministic collations are not supported for operator class \"%s\"",
+ NameStr(((Form_pg_opclass) GETSTRUCT(classtup))->opcname))));
+ ReleaseSysCache(classtup);
+ }
+ }
+ }
+
+ /*
+ * Concurrent index build on a system catalog is unsafe because we tend to
+ * release locks before committing in catalogs.
+ */
+ if (concurrent &&
+ IsCatalogRelation(heapRelation))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("concurrent index creation on system catalog tables is not supported")));
+
+ /*
+ * This case is currently not supported. There's no way to ask for it in
+ * the grammar with CREATE INDEX, but it can happen with REINDEX.
+ */
+ if (concurrent && is_exclusion)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("concurrent index creation for exclusion constraints is not supported")));
+
+ /*
+ * We cannot allow indexing a shared relation after initdb (because
+ * there's no way to make the entry in other databases' pg_class).
+ */
+ if (shared_relation && !IsBootstrapProcessingMode())
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("shared indexes cannot be created after initdb")));
+
+ /*
+ * Shared relations must be in pg_global, too (last-ditch check)
+ */
+ if (shared_relation && tableSpaceId != GLOBALTABLESPACE_OID)
+ elog(ERROR, "shared relations must be placed in pg_global tablespace");
+
+ /*
+ * Check for duplicate name (both as to the index, and as to the
+ * associated constraint if any). Such cases would fail on the relevant
+ * catalogs' unique indexes anyway, but we prefer to give a friendlier
+ * error message.
+ */
+ if (get_relname_relid(indexRelationName, namespaceId))
+ {
+ if ((flags & INDEX_CREATE_IF_NOT_EXISTS) != 0)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_TABLE),
+ errmsg("relation \"%s\" already exists, skipping",
+ indexRelationName)));
+ table_close(pg_class, RowExclusiveLock);
+ return InvalidOid;
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_TABLE),
+ errmsg("relation \"%s\" already exists",
+ indexRelationName)));
+ }
+
+ if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0 &&
+ ConstraintNameIsUsed(CONSTRAINT_RELATION, heapRelationId,
+ indexRelationName))
+ {
+ /*
+ * INDEX_CREATE_IF_NOT_EXISTS does not apply here, since the
+ * conflicting constraint is not an index.
+ */
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("constraint \"%s\" for relation \"%s\" already exists",
+ indexRelationName, RelationGetRelationName(heapRelation))));
+ }
+
+ /*
+ * construct tuple descriptor for index tuples
+ */
+ indexTupDesc = ConstructTupleDescriptor(heapRelation,
+ indexInfo,
+ indexColNames,
+ accessMethodObjectId,
+ collationObjectId,
+ classObjectId);
+
+ /*
+ * Allocate an OID for the index, unless we were told what to use.
+ *
+ * The OID will be the relfilenode as well, so make sure it doesn't
+ * collide with either pg_class OIDs or existing physical files.
+ */
+ if (!OidIsValid(indexRelationId))
+ {
+ /* Use binary-upgrade override for pg_class.oid/relfilenode? */
+ if (IsBinaryUpgrade)
+ {
+ if (!OidIsValid(binary_upgrade_next_index_pg_class_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("pg_class index OID value not set when in binary upgrade mode")));
+
+ indexRelationId = binary_upgrade_next_index_pg_class_oid;
+ binary_upgrade_next_index_pg_class_oid = InvalidOid;
+ }
+ else
+ {
+ indexRelationId =
+ GetNewRelFileNode(tableSpaceId, pg_class, relpersistence);
+ }
+ }
+
+ /*
+ * create the index relation's relcache entry and, if necessary, the
+ * physical disk file. (If we fail further down, it's the smgr's
+ * responsibility to remove the disk file again, if any.)
+ */
+ indexRelation = heap_create(indexRelationName,
+ namespaceId,
+ tableSpaceId,
+ indexRelationId,
+ relFileNode,
+ accessMethodObjectId,
+ indexTupDesc,
+ relkind,
+ relpersistence,
+ shared_relation,
+ mapped_relation,
+ allow_system_table_mods,
+ &relfrozenxid,
+ &relminmxid);
+
+ Assert(relfrozenxid == InvalidTransactionId);
+ Assert(relminmxid == InvalidMultiXactId);
+ Assert(indexRelationId == RelationGetRelid(indexRelation));
+
+ /*
+ * Obtain exclusive lock on it. Although no other transactions can see it
+ * until we commit, this prevents deadlock-risk complaints from lock
+ * manager in cases such as CLUSTER.
+ */
+ LockRelation(indexRelation, AccessExclusiveLock);
+
+ /*
+ * Fill in fields of the index's pg_class entry that are not set correctly
+ * by heap_create.
+ *
+ * XXX should have a cleaner way to create cataloged indexes
+ */
+ indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
+ indexRelation->rd_rel->relam = accessMethodObjectId;
+ indexRelation->rd_rel->relispartition = OidIsValid(parentIndexRelid);
+
+ /*
+ * store index's pg_class entry
+ */
+ InsertPgClassTuple(pg_class, indexRelation,
+ RelationGetRelid(indexRelation),
+ (Datum) 0,
+ reloptions);
+
+ /* done with pg_class */
+ table_close(pg_class, RowExclusiveLock);
+
+ /*
+ * now update the object id's of all the attribute tuple forms in the
+ * index relation's tuple descriptor
+ */
+ InitializeAttributeOids(indexRelation,
+ indexInfo->ii_NumIndexAttrs,
+ indexRelationId);
+
+ /*
+ * append ATTRIBUTE tuples for the index
+ */
+ AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs,
+ indexInfo->ii_OpclassOptions);
+
+ /* ----------------
+ * update pg_index
+ * (append INDEX tuple)
+ *
+ * Note that this stows away a representation of "predicate".
+ * (Or, could define a rule to maintain the predicate) --Nels, Feb '92
+ * ----------------
+ */
+ UpdateIndexRelation(indexRelationId, heapRelationId, parentIndexRelid,
+ indexInfo,
+ collationObjectId, classObjectId, coloptions,
+ isprimary, is_exclusion,
+ (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) == 0,
+ !concurrent && !invalid,
+ !concurrent);
+
+ /*
+ * Register relcache invalidation on the indexes' heap relation, to
+ * maintain consistency of its index list
+ */
+ CacheInvalidateRelcache(heapRelation);
+
+ /* update pg_inherits and the parent's relhassubclass, if needed */
+ if (OidIsValid(parentIndexRelid))
+ {
+ StoreSingleInheritance(indexRelationId, parentIndexRelid, 1);
+ SetRelationHasSubclass(parentIndexRelid, true);
+ }
+
+ /*
+ * Register constraint and dependencies for the index.
+ *
+ * If the index is from a CONSTRAINT clause, construct a pg_constraint
+ * entry. The index will be linked to the constraint, which in turn is
+ * linked to the table. If it's not a CONSTRAINT, we need to make a
+ * dependency directly on the table.
+ *
+ * We don't need a dependency on the namespace, because there'll be an
+ * indirect dependency via our parent table.
+ *
+ * During bootstrap we can't register any dependencies, and we don't try
+ * to make a constraint either.
+ */
+ if (!IsBootstrapProcessingMode())
+ {
+ ObjectAddress myself,
+ referenced;
+
+ myself.classId = RelationRelationId;
+ myself.objectId = indexRelationId;
+ myself.objectSubId = 0;
+
+ if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0)
+ {
+ char constraintType;
+ ObjectAddress localaddr;
+
+ if (isprimary)
+ constraintType = CONSTRAINT_PRIMARY;
+ else if (indexInfo->ii_Unique)
+ constraintType = CONSTRAINT_UNIQUE;
+ else if (is_exclusion)
+ constraintType = CONSTRAINT_EXCLUSION;
+ else
+ {
+ elog(ERROR, "constraint must be PRIMARY, UNIQUE or EXCLUDE");
+ constraintType = 0; /* keep compiler quiet */
+ }
+
+ localaddr = index_constraint_create(heapRelation,
+ indexRelationId,
+ parentConstraintId,
+ indexInfo,
+ indexRelationName,
+ constraintType,
+ constr_flags,
+ allow_system_table_mods,
+ is_internal);
+ if (constraintId)
+ *constraintId = localaddr.objectId;
+ }
+ else
+ {
+ bool have_simple_col = false;
+
+ /* Create auto dependencies on simply-referenced columns */
+ for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+ {
+ if (indexInfo->ii_IndexAttrNumbers[i] != 0)
+ {
+ referenced.classId = RelationRelationId;
+ referenced.objectId = heapRelationId;
+ referenced.objectSubId = indexInfo->ii_IndexAttrNumbers[i];
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+
+ have_simple_col = true;
+ }
+ }
+
+ /*
+ * If there are no simply-referenced columns, give the index an
+ * auto dependency on the whole table. In most cases, this will
+ * be redundant, but it might not be if the index expressions and
+ * predicate contain no Vars or only whole-row Vars.
+ */
+ if (!have_simple_col)
+ {
+ referenced.classId = RelationRelationId;
+ referenced.objectId = heapRelationId;
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+ }
+ }
+
+ /*
+ * If this is an index partition, create partition dependencies on
+ * both the parent index and the table. (Note: these must be *in
+ * addition to*, not instead of, all other dependencies. Otherwise
+ * we'll be short some dependencies after DETACH PARTITION.)
+ */
+ if (OidIsValid(parentIndexRelid))
+ {
+ referenced.classId = RelationRelationId;
+ referenced.objectId = parentIndexRelid;
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_PRI);
+
+ referenced.classId = RelationRelationId;
+ referenced.objectId = heapRelationId;
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_SEC);
+ }
+
+ /* Store dependency on collations */
+ /* The default collation is pinned, so don't bother recording it */
+ for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
+ {
+ if (OidIsValid(collationObjectId[i]) &&
+ collationObjectId[i] != DEFAULT_COLLATION_OID)
+ {
+ referenced.classId = CollationRelationId;
+ referenced.objectId = collationObjectId[i];
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+ }
+
+ /* Store dependency on operator classes */
+ for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
+ {
+ referenced.classId = OperatorClassRelationId;
+ referenced.objectId = classObjectId[i];
+ referenced.objectSubId = 0;
+
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Store dependencies on anything mentioned in index expressions */
+ if (indexInfo->ii_Expressions)
+ {
+ recordDependencyOnSingleRelExpr(&myself,
+ (Node *) indexInfo->ii_Expressions,
+ heapRelationId,
+ DEPENDENCY_NORMAL,
+ DEPENDENCY_AUTO, false);
+ }
+
+ /* Store dependencies on anything mentioned in predicate */
+ if (indexInfo->ii_Predicate)
+ {
+ recordDependencyOnSingleRelExpr(&myself,
+ (Node *) indexInfo->ii_Predicate,
+ heapRelationId,
+ DEPENDENCY_NORMAL,
+ DEPENDENCY_AUTO, false);
+ }
+ }
+ else
+ {
+ /* Bootstrap mode - assert we weren't asked for constraint support */
+ Assert((flags & INDEX_CREATE_ADD_CONSTRAINT) == 0);
+ }
+
+ /* Post creation hook for new index */
+ InvokeObjectPostCreateHookArg(RelationRelationId,
+ indexRelationId, 0, is_internal);
+
+ /*
+ * Advance the command counter so that we can see the newly-entered
+ * catalog tuples for the index.
+ */
+ CommandCounterIncrement();
+
+ /*
+ * In bootstrap mode, we have to fill in the index strategy structure with
+ * information from the catalogs. If we aren't bootstrapping, then the
+ * relcache entry has already been rebuilt thanks to sinval update during
+ * CommandCounterIncrement.
+ */
+ if (IsBootstrapProcessingMode())
+ RelationInitIndexAccessInfo(indexRelation);
+ else
+ Assert(indexRelation->rd_indexcxt != NULL);
+
+ indexRelation->rd_index->indnkeyatts = indexInfo->ii_NumIndexKeyAttrs;
+
+ /* Validate opclass-specific options */
+ if (indexInfo->ii_OpclassOptions)
+ for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
+ (void) index_opclass_options(indexRelation, i + 1,
+ indexInfo->ii_OpclassOptions[i],
+ true);
+
+ /*
+ * If this is bootstrap (initdb) time, then we don't actually fill in the
+ * index yet. We'll be creating more indexes and classes later, so we
+ * delay filling them in until just before we're done with bootstrapping.
+ * Similarly, if the caller specified to skip the build then filling the
+ * index is delayed till later (ALTER TABLE can save work in some cases
+ * with this). Otherwise, we call the AM routine that constructs the
+ * index.
+ */
+ if (IsBootstrapProcessingMode())
+ {
+ index_register(heapRelationId, indexRelationId, indexInfo);
+ }
+ else if ((flags & INDEX_CREATE_SKIP_BUILD) != 0)
+ {
+ /*
+ * Caller is responsible for filling the index later on. However,
+ * we'd better make sure that the heap relation is correctly marked as
+ * having an index.
+ */
+ index_update_stats(heapRelation,
+ true,
+ -1.0);
+ /* Make the above update visible */
+ CommandCounterIncrement();
+ }
+ else
+ {
+ index_build(heapRelation, indexRelation, indexInfo, false, true);
+ }
+
+ /*
+ * Close the index; but we keep the lock that we acquired above until end
+ * of transaction. Closing the heap is caller's responsibility.
+ */
+ index_close(indexRelation, NoLock);
+
+ return indexRelationId;
+}
+
+/*
+ * index_concurrently_create_copy
+ *
+ * Create concurrently an index based on the definition of the one provided by
+ * caller. The index is inserted into catalogs and needs to be built later
+ * on. This is called during concurrent reindex processing.
+ */
+Oid
+index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId, const char *newName)
+{
+ Relation indexRelation;
+ IndexInfo *oldInfo,
+ *newInfo;
+ Oid newIndexId = InvalidOid;
+ HeapTuple indexTuple,
+ classTuple;
+ Datum indclassDatum,
+ colOptionDatum,
+ optionDatum;
+ oidvector *indclass;
+ int2vector *indcoloptions;
+ bool isnull;
+ List *indexColNames = NIL;
+ List *indexExprs = NIL;
+ List *indexPreds = NIL;
+
+ indexRelation = index_open(oldIndexId, RowExclusiveLock);
+
+ /* The new index needs some information from the old index */
+ oldInfo = BuildIndexInfo(indexRelation);
+
+ /*
+ * Concurrent build of an index with exclusion constraints is not
+ * supported.
+ */
+ if (oldInfo->ii_ExclusionOps != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("concurrent index creation for exclusion constraints is not supported")));
+
+ /* Get the array of class and column options IDs from index info */
+ indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(oldIndexId));
+ if (!HeapTupleIsValid(indexTuple))
+ elog(ERROR, "cache lookup failed for index %u", oldIndexId);
+ indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
+ Anum_pg_index_indclass, &isnull);
+ Assert(!isnull);
+ indclass = (oidvector *) DatumGetPointer(indclassDatum);
+
+ colOptionDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
+ Anum_pg_index_indoption, &isnull);
+ Assert(!isnull);
+ indcoloptions = (int2vector *) DatumGetPointer(colOptionDatum);
+
+ /* Fetch options of index if any */
+ classTuple = SearchSysCache1(RELOID, oldIndexId);
+ if (!HeapTupleIsValid(classTuple))
+ elog(ERROR, "cache lookup failed for relation %u", oldIndexId);
+ optionDatum = SysCacheGetAttr(RELOID, classTuple,
+ Anum_pg_class_reloptions, &isnull);
+
+ /*
+ * Fetch the list of expressions and predicates directly from the
+ * catalogs. This cannot rely on the information from IndexInfo of the
+ * old index as these have been flattened for the planner.
+ */
+ if (oldInfo->ii_Expressions != NIL)
+ {
+ Datum exprDatum;
+ char *exprString;
+
+ exprDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
+ Anum_pg_index_indexprs, &isnull);
+ Assert(!isnull);
+ exprString = TextDatumGetCString(exprDatum);
+ indexExprs = (List *) stringToNode(exprString);
+ pfree(exprString);
+ }
+ if (oldInfo->ii_Predicate != NIL)
+ {
+ Datum predDatum;
+ char *predString;
+
+ predDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
+ Anum_pg_index_indpred, &isnull);
+ Assert(!isnull);
+ predString = TextDatumGetCString(predDatum);
+ indexPreds = (List *) stringToNode(predString);
+
+ /* Also convert to implicit-AND format */
+ indexPreds = make_ands_implicit((Expr *) indexPreds);
+ pfree(predString);
+ }
+
+ /*
+ * Build the index information for the new index. Note that rebuild of
+ * indexes with exclusion constraints is not supported, hence there is no
+ * need to fill all the ii_Exclusion* fields.
+ */
+ newInfo = makeIndexInfo(oldInfo->ii_NumIndexAttrs,
+ oldInfo->ii_NumIndexKeyAttrs,
+ oldInfo->ii_Am,
+ indexExprs,
+ indexPreds,
+ oldInfo->ii_Unique,
+ false, /* not ready for inserts */
+ true);
+
+ /*
+ * Extract the list of column names and the column numbers for the new
+ * index information. All this information will be used for the index
+ * creation.
+ */
+ for (int i = 0; i < oldInfo->ii_NumIndexAttrs; i++)
+ {
+ TupleDesc indexTupDesc = RelationGetDescr(indexRelation);
+ Form_pg_attribute att = TupleDescAttr(indexTupDesc, i);
+
+ indexColNames = lappend(indexColNames, NameStr(att->attname));
+ newInfo->ii_IndexAttrNumbers[i] = oldInfo->ii_IndexAttrNumbers[i];
+ }
+
+ /*
+ * Now create the new index.
+ *
+ * For a partition index, we adjust the partition dependency later, to
+ * ensure a consistent state at all times. That is why parentIndexRelid
+ * is not set here.
+ */
+ newIndexId = index_create(heapRelation,
+ newName,
+ InvalidOid, /* indexRelationId */
+ InvalidOid, /* parentIndexRelid */
+ InvalidOid, /* parentConstraintId */
+ InvalidOid, /* relFileNode */
+ newInfo,
+ indexColNames,
+ indexRelation->rd_rel->relam,
+ indexRelation->rd_rel->reltablespace,
+ indexRelation->rd_indcollation,
+ indclass->values,
+ indcoloptions->values,
+ optionDatum,
+ INDEX_CREATE_SKIP_BUILD | INDEX_CREATE_CONCURRENT,
+ 0,
+ true, /* allow table to be a system catalog? */
+ false, /* is_internal? */
+ NULL);
+
+ /* Close the relations used and clean up */
+ index_close(indexRelation, NoLock);
+ ReleaseSysCache(indexTuple);
+ ReleaseSysCache(classTuple);
+
+ return newIndexId;
+}
+
+/*
+ * index_concurrently_build
+ *
+ * Build index for a concurrent operation. Low-level locks are taken when
+ * this operation is performed to prevent only schema changes, but they need
+ * to be kept until the end of the transaction performing this operation.
+ * 'indexOid' refers to an index relation OID already created as part of
+ * previous processing, and 'heapOid' refers to its parent heap relation.
+ */
+void
+index_concurrently_build(Oid heapRelationId,
+ Oid indexRelationId)
+{
+ Relation heapRel;
+ Relation indexRelation;
+ IndexInfo *indexInfo;
+
+ /* This had better make sure that a snapshot is active */
+ Assert(ActiveSnapshotSet());
+
+ /* Open and lock the parent heap relation */
+ heapRel = table_open(heapRelationId, ShareUpdateExclusiveLock);
+
+ /* And the target index relation */
+ indexRelation = index_open(indexRelationId, RowExclusiveLock);
+
+ /*
+ * We have to re-build the IndexInfo struct, since it was lost in the
+ * commit of the transaction where this concurrent index was created at
+ * the catalog level.
+ */
+ indexInfo = BuildIndexInfo(indexRelation);
+ Assert(!indexInfo->ii_ReadyForInserts);
+ indexInfo->ii_Concurrent = true;
+ indexInfo->ii_BrokenHotChain = false;
+
+ /* Now build the index */
+ index_build(heapRel, indexRelation, indexInfo, false, true);
+
+ /* Close both the relations, but keep the locks */
+ table_close(heapRel, NoLock);
+ index_close(indexRelation, NoLock);
+
+ /*
+ * Update the pg_index row to mark the index as ready for inserts. Once we
+ * commit this transaction, any new transactions that open the table must
+ * insert new entries into the index for insertions and non-HOT updates.
+ */
+ index_set_state_flags(indexRelationId, INDEX_CREATE_SET_READY);
+}
+
+/*
+ * index_concurrently_swap
+ *
+ * Swap name, dependencies, and constraints of the old index over to the new
+ * index, while marking the old index as invalid and the new as valid.
+ */
+void
+index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
+{
+ Relation pg_class,
+ pg_index,
+ pg_constraint,
+ pg_trigger;
+ Relation oldClassRel,
+ newClassRel;
+ HeapTuple oldClassTuple,
+ newClassTuple;
+ Form_pg_class oldClassForm,
+ newClassForm;
+ HeapTuple oldIndexTuple,
+ newIndexTuple;
+ Form_pg_index oldIndexForm,
+ newIndexForm;
+ bool isPartition;
+ Oid indexConstraintOid;
+ List *constraintOids = NIL;
+ ListCell *lc;
+
+ /*
+ * Take a necessary lock on the old and new index before swapping them.
+ */
+ oldClassRel = relation_open(oldIndexId, ShareUpdateExclusiveLock);
+ newClassRel = relation_open(newIndexId, ShareUpdateExclusiveLock);
+
+ /* Now swap names and dependencies of those indexes */
+ pg_class = table_open(RelationRelationId, RowExclusiveLock);
+
+ oldClassTuple = SearchSysCacheCopy1(RELOID,
+ ObjectIdGetDatum(oldIndexId));
+ if (!HeapTupleIsValid(oldClassTuple))
+ elog(ERROR, "could not find tuple for relation %u", oldIndexId);
+ newClassTuple = SearchSysCacheCopy1(RELOID,
+ ObjectIdGetDatum(newIndexId));
+ if (!HeapTupleIsValid(newClassTuple))
+ elog(ERROR, "could not find tuple for relation %u", newIndexId);
+
+ oldClassForm = (Form_pg_class) GETSTRUCT(oldClassTuple);
+ newClassForm = (Form_pg_class) GETSTRUCT(newClassTuple);
+
+ /* Swap the names */
+ namestrcpy(&newClassForm->relname, NameStr(oldClassForm->relname));
+ namestrcpy(&oldClassForm->relname, oldName);
+
+ /* Swap the partition flags to track inheritance properly */
+ isPartition = newClassForm->relispartition;
+ newClassForm->relispartition = oldClassForm->relispartition;
+ oldClassForm->relispartition = isPartition;
+
+ CatalogTupleUpdate(pg_class, &oldClassTuple->t_self, oldClassTuple);
+ CatalogTupleUpdate(pg_class, &newClassTuple->t_self, newClassTuple);
+
+ heap_freetuple(oldClassTuple);
+ heap_freetuple(newClassTuple);
+
+ /* Now swap index info */
+ pg_index = table_open(IndexRelationId, RowExclusiveLock);
+
+ oldIndexTuple = SearchSysCacheCopy1(INDEXRELID,
+ ObjectIdGetDatum(oldIndexId));
+ if (!HeapTupleIsValid(oldIndexTuple))
+ elog(ERROR, "could not find tuple for relation %u", oldIndexId);
+ newIndexTuple = SearchSysCacheCopy1(INDEXRELID,
+ ObjectIdGetDatum(newIndexId));
+ if (!HeapTupleIsValid(newIndexTuple))
+ elog(ERROR, "could not find tuple for relation %u", newIndexId);
+
+ oldIndexForm = (Form_pg_index) GETSTRUCT(oldIndexTuple);
+ newIndexForm = (Form_pg_index) GETSTRUCT(newIndexTuple);
+
+ /*
+ * Copy constraint flags from the old index. This is safe because the old
+ * index guaranteed uniqueness.
+ */
+ newIndexForm->indisprimary = oldIndexForm->indisprimary;
+ oldIndexForm->indisprimary = false;
+ newIndexForm->indisexclusion = oldIndexForm->indisexclusion;
+ oldIndexForm->indisexclusion = false;
+ newIndexForm->indimmediate = oldIndexForm->indimmediate;
+ oldIndexForm->indimmediate = true;
+
+ /* Preserve indisreplident in the new index */
+ newIndexForm->indisreplident = oldIndexForm->indisreplident;
+ oldIndexForm->indisreplident = false;
+
+ /* Preserve indisclustered in the new index */
+ newIndexForm->indisclustered = oldIndexForm->indisclustered;
+
+ /*
+ * Mark the new index as valid, and the old index as invalid similarly to
+ * what index_set_state_flags() does.
+ */
+ newIndexForm->indisvalid = true;
+ oldIndexForm->indisvalid = false;
+ oldIndexForm->indisclustered = false;
+
+ CatalogTupleUpdate(pg_index, &oldIndexTuple->t_self, oldIndexTuple);
+ CatalogTupleUpdate(pg_index, &newIndexTuple->t_self, newIndexTuple);
+
+ heap_freetuple(oldIndexTuple);
+ heap_freetuple(newIndexTuple);
+
+ /*
+ * Move constraints and triggers over to the new index
+ */
+
+ constraintOids = get_index_ref_constraints(oldIndexId);
+
+ indexConstraintOid = get_index_constraint(oldIndexId);
+
+ if (OidIsValid(indexConstraintOid))
+ constraintOids = lappend_oid(constraintOids, indexConstraintOid);
+
+ pg_constraint = table_open(ConstraintRelationId, RowExclusiveLock);
+ pg_trigger = table_open(TriggerRelationId, RowExclusiveLock);
+
+ foreach(lc, constraintOids)
+ {
+ HeapTuple constraintTuple,
+ triggerTuple;
+ Form_pg_constraint conForm;
+ ScanKeyData key[1];
+ SysScanDesc scan;
+ Oid constraintOid = lfirst_oid(lc);
+
+ /* Move the constraint from the old to the new index */
+ constraintTuple = SearchSysCacheCopy1(CONSTROID,
+ ObjectIdGetDatum(constraintOid));
+ if (!HeapTupleIsValid(constraintTuple))
+ elog(ERROR, "could not find tuple for constraint %u", constraintOid);
+
+ conForm = ((Form_pg_constraint) GETSTRUCT(constraintTuple));
+
+ if (conForm->conindid == oldIndexId)
+ {
+ conForm->conindid = newIndexId;
+
+ CatalogTupleUpdate(pg_constraint, &constraintTuple->t_self, constraintTuple);
+ }
+
+ heap_freetuple(constraintTuple);
+
+ /* Search for trigger records */
+ ScanKeyInit(&key[0],
+ Anum_pg_trigger_tgconstraint,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(constraintOid));
+
+ scan = systable_beginscan(pg_trigger, TriggerConstraintIndexId, true,
+ NULL, 1, key);
+
+ while (HeapTupleIsValid((triggerTuple = systable_getnext(scan))))
+ {
+ Form_pg_trigger tgForm = (Form_pg_trigger) GETSTRUCT(triggerTuple);
+
+ if (tgForm->tgconstrindid != oldIndexId)
+ continue;
+
+ /* Make a modifiable copy */
+ triggerTuple = heap_copytuple(triggerTuple);
+ tgForm = (Form_pg_trigger) GETSTRUCT(triggerTuple);
+
+ tgForm->tgconstrindid = newIndexId;
+
+ CatalogTupleUpdate(pg_trigger, &triggerTuple->t_self, triggerTuple);
+
+ heap_freetuple(triggerTuple);
+ }
+
+ systable_endscan(scan);
+ }
+
+ /*
+ * Move comment if any
+ */
+ {
+ Relation description;
+ ScanKeyData skey[3];
+ SysScanDesc sd;
+ HeapTuple tuple;
+ Datum values[Natts_pg_description] = {0};
+ bool nulls[Natts_pg_description] = {0};
+ bool replaces[Natts_pg_description] = {0};
+
+ values[Anum_pg_description_objoid - 1] = ObjectIdGetDatum(newIndexId);
+ replaces[Anum_pg_description_objoid - 1] = true;
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_description_objoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(oldIndexId));
+ ScanKeyInit(&skey[1],
+ Anum_pg_description_classoid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationRelationId));
+ ScanKeyInit(&skey[2],
+ Anum_pg_description_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(0));
+
+ description = table_open(DescriptionRelationId, RowExclusiveLock);
+
+ sd = systable_beginscan(description, DescriptionObjIndexId, true,
+ NULL, 3, skey);
+
+ while ((tuple = systable_getnext(sd)) != NULL)
+ {
+ tuple = heap_modify_tuple(tuple, RelationGetDescr(description),
+ values, nulls, replaces);
+ CatalogTupleUpdate(description, &tuple->t_self, tuple);
+
+ break; /* Assume there can be only one match */
+ }
+
+ systable_endscan(sd);
+ table_close(description, NoLock);
+ }
+
+ /*
+ * Swap inheritance relationship with parent index
+ */
+ if (get_rel_relispartition(oldIndexId))
+ {
+ List *ancestors = get_partition_ancestors(oldIndexId);
+ Oid parentIndexRelid = linitial_oid(ancestors);
+
+ DeleteInheritsTuple(oldIndexId, parentIndexRelid);
+ StoreSingleInheritance(newIndexId, parentIndexRelid, 1);
+
+ list_free(ancestors);
+ }
+
+ /*
+ * Swap all dependencies of and on the old index to the new one, and
+ * vice-versa. Note that a call to CommandCounterIncrement() would cause
+ * duplicate entries in pg_depend, so this should not be done.
+ */
+ changeDependenciesOf(RelationRelationId, newIndexId, oldIndexId);
+ changeDependenciesOn(RelationRelationId, newIndexId, oldIndexId);
+
+ changeDependenciesOf(RelationRelationId, oldIndexId, newIndexId);
+ changeDependenciesOn(RelationRelationId, oldIndexId, newIndexId);
+
+ /*
+ * Copy over statistics from old to new index
+ */
+ {
+ PgStat_StatTabEntry *tabentry;
+
+ tabentry = pgstat_fetch_stat_tabentry(oldIndexId);
+ if (tabentry)
+ {
+ if (newClassRel->pgstat_info)
+ {
+ newClassRel->pgstat_info->t_counts.t_numscans = tabentry->numscans;
+ newClassRel->pgstat_info->t_counts.t_tuples_returned = tabentry->tuples_returned;
+ newClassRel->pgstat_info->t_counts.t_tuples_fetched = tabentry->tuples_fetched;
+ newClassRel->pgstat_info->t_counts.t_blocks_fetched = tabentry->blocks_fetched;
+ newClassRel->pgstat_info->t_counts.t_blocks_hit = tabentry->blocks_hit;
+
+ /*
+ * The data will be sent by the next pgstat_report_stat()
+ * call.
+ */
+ }
+ }
+ }
+
+ /* Copy data of pg_statistic from the old index to the new one */
+ CopyStatistics(oldIndexId, newIndexId);
+
+ /* Copy pg_attribute.attstattarget for each index attribute */
+ {
+ HeapTuple attrTuple;
+ Relation pg_attribute;
+ SysScanDesc scan;
+ ScanKeyData key[1];
+
+ pg_attribute = table_open(AttributeRelationId, RowExclusiveLock);
+ ScanKeyInit(&key[0],
+ Anum_pg_attribute_attrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(newIndexId));
+ scan = systable_beginscan(pg_attribute, AttributeRelidNumIndexId,
+ true, NULL, 1, key);
+
+ while (HeapTupleIsValid((attrTuple = systable_getnext(scan))))
+ {
+ Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attrTuple);
+ Datum repl_val[Natts_pg_attribute];
+ bool repl_null[Natts_pg_attribute];
+ bool repl_repl[Natts_pg_attribute];
+ int attstattarget;
+ HeapTuple newTuple;
+
+ /* Ignore dropped columns */
+ if (att->attisdropped)
+ continue;
+
+ /*
+ * Get attstattarget from the old index and refresh the new value.
+ */
+ attstattarget = get_attstattarget(oldIndexId, att->attnum);
+
+ /* no need for a refresh if both match */
+ if (attstattarget == att->attstattarget)
+ continue;
+
+ memset(repl_val, 0, sizeof(repl_val));
+ memset(repl_null, false, sizeof(repl_null));
+ memset(repl_repl, false, sizeof(repl_repl));
+
+ repl_repl[Anum_pg_attribute_attstattarget - 1] = true;
+ repl_val[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(attstattarget);
+
+ newTuple = heap_modify_tuple(attrTuple,
+ RelationGetDescr(pg_attribute),
+ repl_val, repl_null, repl_repl);
+ CatalogTupleUpdate(pg_attribute, &newTuple->t_self, newTuple);
+
+ heap_freetuple(newTuple);
+ }
+
+ systable_endscan(scan);
+ table_close(pg_attribute, RowExclusiveLock);
+ }
+
+ /* Close relations */
+ table_close(pg_class, RowExclusiveLock);
+ table_close(pg_index, RowExclusiveLock);
+ table_close(pg_constraint, RowExclusiveLock);
+ table_close(pg_trigger, RowExclusiveLock);
+
+ /* The lock taken previously is not released until the end of transaction */
+ relation_close(oldClassRel, NoLock);
+ relation_close(newClassRel, NoLock);
+}
+
+/*
+ * index_concurrently_set_dead
+ *
+ * Perform the last invalidation stage of DROP INDEX CONCURRENTLY or REINDEX
+ * CONCURRENTLY before actually dropping the index. After calling this
+ * function, the index is seen by all the backends as dead. Low-level locks
+ * taken here are kept until the end of the transaction calling this function.
+ */
+void
+index_concurrently_set_dead(Oid heapId, Oid indexId)
+{
+ Relation userHeapRelation;
+ Relation userIndexRelation;
+
+ /*
+ * No more predicate locks will be acquired on this index, and we're about
+ * to stop doing inserts into the index which could show conflicts with
+ * existing predicate locks, so now is the time to move them to the heap
+ * relation.
+ */
+ userHeapRelation = table_open(heapId, ShareUpdateExclusiveLock);
+ userIndexRelation = index_open(indexId, ShareUpdateExclusiveLock);
+ TransferPredicateLocksToHeapRelation(userIndexRelation);
+
+ /*
+ * Now we are sure that nobody uses the index for queries; they just might
+ * have it open for updating it. So now we can unset indisready and
+ * indislive, then wait till nobody could be using it at all anymore.
+ */
+ index_set_state_flags(indexId, INDEX_DROP_SET_DEAD);
+
+ /*
+ * Invalidate the relcache for the table, so that after this commit all
+ * sessions will refresh the table's index list. Forgetting just the
+ * index's relcache entry is not enough.
+ */
+ CacheInvalidateRelcache(userHeapRelation);
+
+ /*
+ * Close the relations again, though still holding session lock.
+ */
+ table_close(userHeapRelation, NoLock);
+ index_close(userIndexRelation, NoLock);
+}
+
+/*
+ * index_constraint_create
+ *
+ * Set up a constraint associated with an index. Return the new constraint's
+ * address.
+ *
+ * heapRelation: table owning the index (must be suitably locked by caller)
+ * indexRelationId: OID of the index
+ * parentConstraintId: if constraint is on a partition, the OID of the
+ * constraint in the parent.
+ * indexInfo: same info executor uses to insert into the index
+ * constraintName: what it say (generally, should match name of index)
+ * constraintType: one of CONSTRAINT_PRIMARY, CONSTRAINT_UNIQUE, or
+ * CONSTRAINT_EXCLUSION
+ * flags: bitmask that can include any combination of these bits:
+ * INDEX_CONSTR_CREATE_MARK_AS_PRIMARY: index is a PRIMARY KEY
+ * INDEX_CONSTR_CREATE_DEFERRABLE: constraint is DEFERRABLE
+ * INDEX_CONSTR_CREATE_INIT_DEFERRED: constraint is INITIALLY DEFERRED
+ * INDEX_CONSTR_CREATE_UPDATE_INDEX: update the pg_index row
+ * INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS: remove existing dependencies
+ * of index on table's columns
+ * allow_system_table_mods: allow table to be a system catalog
+ * is_internal: index is constructed due to internal process
+ */
+ObjectAddress
+index_constraint_create(Relation heapRelation,
+ Oid indexRelationId,
+ Oid parentConstraintId,
+ IndexInfo *indexInfo,
+ const char *constraintName,
+ char constraintType,
+ bits16 constr_flags,
+ bool allow_system_table_mods,
+ bool is_internal)
+{
+ Oid namespaceId = RelationGetNamespace(heapRelation);
+ ObjectAddress myself,
+ idxaddr;
+ Oid conOid;
+ bool deferrable;
+ bool initdeferred;
+ bool mark_as_primary;
+ bool islocal;
+ bool noinherit;
+ int inhcount;
+
+ deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0;
+ initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0;
+ mark_as_primary = (constr_flags & INDEX_CONSTR_CREATE_MARK_AS_PRIMARY) != 0;
+
+ /* constraint creation support doesn't work while bootstrapping */
+ Assert(!IsBootstrapProcessingMode());
+
+ /* enforce system-table restriction */
+ if (!allow_system_table_mods &&
+ IsSystemRelation(heapRelation) &&
+ IsNormalProcessingMode())
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("user-defined indexes on system catalog tables are not supported")));
+
+ /* primary/unique constraints shouldn't have any expressions */
+ if (indexInfo->ii_Expressions &&
+ constraintType != CONSTRAINT_EXCLUSION)
+ elog(ERROR, "constraints cannot have index expressions");
+
+ /*
+ * If we're manufacturing a constraint for a pre-existing index, we need
+ * to get rid of the existing auto dependencies for the index (the ones
+ * that index_create() would have made instead of calling this function).
+ *
+ * Note: this code would not necessarily do the right thing if the index
+ * has any expressions or predicate, but we'd never be turning such an
+ * index into a UNIQUE or PRIMARY KEY constraint.
+ */
+ if (constr_flags & INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS)
+ deleteDependencyRecordsForClass(RelationRelationId, indexRelationId,
+ RelationRelationId, DEPENDENCY_AUTO);
+
+ if (OidIsValid(parentConstraintId))
+ {
+ islocal = false;
+ inhcount = 1;
+ noinherit = false;
+ }
+ else
+ {
+ islocal = true;
+ inhcount = 0;
+ noinherit = true;
+ }
+
+ /*
+ * Construct a pg_constraint entry.
+ */
+ conOid = CreateConstraintEntry(constraintName,
+ namespaceId,
+ constraintType,
+ deferrable,
+ initdeferred,
+ true,
+ parentConstraintId,
+ RelationGetRelid(heapRelation),
+ indexInfo->ii_IndexAttrNumbers,
+ indexInfo->ii_NumIndexKeyAttrs,
+ indexInfo->ii_NumIndexAttrs,
+ InvalidOid, /* no domain */
+ indexRelationId, /* index OID */
+ InvalidOid, /* no foreign key */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ ' ',
+ ' ',
+ ' ',
+ indexInfo->ii_ExclusionOps,
+ NULL, /* no check constraint */
+ NULL,
+ islocal,
+ inhcount,
+ noinherit,
+ is_internal);
+
+ /*
+ * Register the index as internally dependent on the constraint.
+ *
+ * Note that the constraint has a dependency on the table, so we don't
+ * need (or want) any direct dependency from the index to the table.
+ */
+ ObjectAddressSet(myself, ConstraintRelationId, conOid);
+ ObjectAddressSet(idxaddr, RelationRelationId, indexRelationId);
+ recordDependencyOn(&idxaddr, &myself, DEPENDENCY_INTERNAL);
+
+ /*
+ * Also, if this is a constraint on a partition, give it partition-type
+ * dependencies on the parent constraint as well as the table.
+ */
+ if (OidIsValid(parentConstraintId))
+ {
+ ObjectAddress referenced;
+
+ ObjectAddressSet(referenced, ConstraintRelationId, parentConstraintId);
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_PRI);
+ ObjectAddressSet(referenced, RelationRelationId,
+ RelationGetRelid(heapRelation));
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_SEC);
+ }
+
+ /*
+ * If the constraint is deferrable, create the deferred uniqueness
+ * checking trigger. (The trigger will be given an internal dependency on
+ * the constraint by CreateTrigger.)
+ */
+ if (deferrable)
+ {
+ CreateTrigStmt *trigger;
+
+ trigger = makeNode(CreateTrigStmt);
+ trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ?
+ "PK_ConstraintTrigger" :
+ "Unique_ConstraintTrigger";
+ trigger->relation = NULL;
+ trigger->funcname = SystemFuncName("unique_key_recheck");
+ trigger->args = NIL;
+ trigger->row = true;
+ trigger->timing = TRIGGER_TYPE_AFTER;
+ trigger->events = TRIGGER_TYPE_INSERT | TRIGGER_TYPE_UPDATE;
+ trigger->columns = NIL;
+ trigger->whenClause = NULL;
+ trigger->isconstraint = true;
+ trigger->deferrable = true;
+ trigger->initdeferred = initdeferred;
+ trigger->constrrel = NULL;
+
+ (void) CreateTrigger(trigger, NULL, RelationGetRelid(heapRelation),
+ InvalidOid, conOid, indexRelationId, InvalidOid,
+ InvalidOid, NULL, true, false);
+ }
+
+ /*
+ * If needed, mark the index as primary and/or deferred in pg_index.
+ *
+ * Note: When making an existing index into a constraint, caller must have
+ * a table lock that prevents concurrent table updates; otherwise, there
+ * is a risk that concurrent readers of the table will miss seeing this
+ * index at all.
+ */
+ if ((constr_flags & INDEX_CONSTR_CREATE_UPDATE_INDEX) &&
+ (mark_as_primary || deferrable))
+ {
+ Relation pg_index;
+ HeapTuple indexTuple;
+ Form_pg_index indexForm;
+ bool dirty = false;
+
+ pg_index = table_open(IndexRelationId, RowExclusiveLock);
+
+ indexTuple = SearchSysCacheCopy1(INDEXRELID,
+ ObjectIdGetDatum(indexRelationId));
+ if (!HeapTupleIsValid(indexTuple))
+ elog(ERROR, "cache lookup failed for index %u", indexRelationId);
+ indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
+
+ if (mark_as_primary && !indexForm->indisprimary)
+ {
+ indexForm->indisprimary = true;
+ dirty = true;
+ }
+
+ if (deferrable && indexForm->indimmediate)
+ {
+ indexForm->indimmediate = false;
+ dirty = true;
+ }
+
+ if (dirty)
+ {
+ CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
+
+ InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0,
+ InvalidOid, is_internal);
+ }
+
+ heap_freetuple(indexTuple);
+ table_close(pg_index, RowExclusiveLock);
+ }
+
+ return myself;
+}
+
+/*
+ * index_drop
+ *
+ * NOTE: this routine should now only be called through performDeletion(),
+ * else associated dependencies won't be cleaned up.
+ *
+ * If concurrent is true, do a DROP INDEX CONCURRENTLY. If concurrent is
+ * false but concurrent_lock_mode is true, then do a normal DROP INDEX but
+ * take a lock for CONCURRENTLY processing. That is used as part of REINDEX
+ * CONCURRENTLY.
+ */
+void
+index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode)
+{
+ Oid heapId;
+ Relation userHeapRelation;
+ Relation userIndexRelation;
+ Relation indexRelation;
+ HeapTuple tuple;
+ bool hasexprs;
+ LockRelId heaprelid,
+ indexrelid;
+ LOCKTAG heaplocktag;
+ LOCKMODE lockmode;
+
+ /*
+ * A temporary relation uses a non-concurrent DROP. Other backends can't
+ * access a temporary relation, so there's no harm in grabbing a stronger
+ * lock (see comments in RemoveRelations), and a non-concurrent DROP is
+ * more efficient.
+ */
+ Assert(get_rel_persistence(indexId) != RELPERSISTENCE_TEMP ||
+ (!concurrent && !concurrent_lock_mode));
+
+ /*
+ * To drop an index safely, we must grab exclusive lock on its parent
+ * table. Exclusive lock on the index alone is insufficient because
+ * another backend might be about to execute a query on the parent table.
+ * If it relies on a previously cached list of index OIDs, then it could
+ * attempt to access the just-dropped index. We must therefore take a
+ * table lock strong enough to prevent all queries on the table from
+ * proceeding until we commit and send out a shared-cache-inval notice
+ * that will make them update their index lists.
+ *
+ * In the concurrent case we avoid this requirement by disabling index use
+ * in multiple steps and waiting out any transactions that might be using
+ * the index, so we don't need exclusive lock on the parent table. Instead
+ * we take ShareUpdateExclusiveLock, to ensure that two sessions aren't
+ * doing CREATE/DROP INDEX CONCURRENTLY on the same index. (We will get
+ * AccessExclusiveLock on the index below, once we're sure nobody else is
+ * using it.)
+ */
+ heapId = IndexGetRelation(indexId, false);
+ lockmode = (concurrent || concurrent_lock_mode) ? ShareUpdateExclusiveLock : AccessExclusiveLock;
+ userHeapRelation = table_open(heapId, lockmode);
+ userIndexRelation = index_open(indexId, lockmode);
+
+ /*
+ * We might still have open queries using it in our own session, which the
+ * above locking won't prevent, so test explicitly.
+ */
+ CheckTableNotInUse(userIndexRelation, "DROP INDEX");
+
+ /*
+ * Drop Index Concurrently is more or less the reverse process of Create
+ * Index Concurrently.
+ *
+ * First we unset indisvalid so queries starting afterwards don't use the
+ * index to answer queries anymore. We have to keep indisready = true so
+ * transactions that are still scanning the index can continue to see
+ * valid index contents. For instance, if they are using READ COMMITTED
+ * mode, and another transaction makes changes and commits, they need to
+ * see those new tuples in the index.
+ *
+ * After all transactions that could possibly have used the index for
+ * queries end, we can unset indisready and indislive, then wait till
+ * nobody could be touching it anymore. (Note: we need indislive because
+ * this state must be distinct from the initial state during CREATE INDEX
+ * CONCURRENTLY, which has indislive true while indisready and indisvalid
+ * are false. That's because in that state, transactions must examine the
+ * index for HOT-safety decisions, while in this state we don't want them
+ * to open it at all.)
+ *
+ * Since all predicate locks on the index are about to be made invalid, we
+ * must promote them to predicate locks on the heap. In the
+ * non-concurrent case we can just do that now. In the concurrent case
+ * it's a bit trickier. The predicate locks must be moved when there are
+ * no index scans in progress on the index and no more can subsequently
+ * start, so that no new predicate locks can be made on the index. Also,
+ * they must be moved before heap inserts stop maintaining the index, else
+ * the conflict with the predicate lock on the index gap could be missed
+ * before the lock on the heap relation is in place to detect a conflict
+ * based on the heap tuple insert.
+ */
+ if (concurrent)
+ {
+ /*
+ * We must commit our transaction in order to make the first pg_index
+ * state update visible to other sessions. If the DROP machinery has
+ * already performed any other actions (removal of other objects,
+ * pg_depend entries, etc), the commit would make those actions
+ * permanent, which would leave us with inconsistent catalog state if
+ * we fail partway through the following sequence. Since DROP INDEX
+ * CONCURRENTLY is restricted to dropping just one index that has no
+ * dependencies, we should get here before anything's been done ---
+ * but let's check that to be sure. We can verify that the current
+ * transaction has not executed any transactional updates by checking
+ * that no XID has been assigned.
+ */
+ if (GetTopTransactionIdIfAny() != InvalidTransactionId)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("DROP INDEX CONCURRENTLY must be first action in transaction")));
+
+ /*
+ * Mark index invalid by updating its pg_index entry
+ */
+ index_set_state_flags(indexId, INDEX_DROP_CLEAR_VALID);
+
+ /*
+ * Invalidate the relcache for the table, so that after this commit
+ * all sessions will refresh any cached plans that might reference the
+ * index.
+ */
+ CacheInvalidateRelcache(userHeapRelation);
+
+ /* save lockrelid and locktag for below, then close but keep locks */
+ heaprelid = userHeapRelation->rd_lockInfo.lockRelId;
+ SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
+ indexrelid = userIndexRelation->rd_lockInfo.lockRelId;
+
+ table_close(userHeapRelation, NoLock);
+ index_close(userIndexRelation, NoLock);
+
+ /*
+ * We must commit our current transaction so that the indisvalid
+ * update becomes visible to other transactions; then start another.
+ * Note that any previously-built data structures are lost in the
+ * commit. The only data we keep past here are the relation IDs.
+ *
+ * Before committing, get a session-level lock on the table, to ensure
+ * that neither it nor the index can be dropped before we finish. This
+ * cannot block, even if someone else is waiting for access, because
+ * we already have the same lock within our transaction.
+ */
+ LockRelationIdForSession(&heaprelid, ShareUpdateExclusiveLock);
+ LockRelationIdForSession(&indexrelid, ShareUpdateExclusiveLock);
+
+ PopActiveSnapshot();
+ CommitTransactionCommand();
+ StartTransactionCommand();
+
+ /*
+ * Now we must wait until no running transaction could be using the
+ * index for a query. Use AccessExclusiveLock here to check for
+ * running transactions that hold locks of any kind on the table. Note
+ * we do not need to worry about xacts that open the table for reading
+ * after this point; they will see the index as invalid when they open
+ * the relation.
+ *
+ * Note: the reason we use actual lock acquisition here, rather than
+ * just checking the ProcArray and sleeping, is that deadlock is
+ * possible if one of the transactions in question is blocked trying
+ * to acquire an exclusive lock on our table. The lock code will
+ * detect deadlock and error out properly.
+ *
+ * Note: we report progress through WaitForLockers() unconditionally
+ * here, even though it will only be used when we're called by REINDEX
+ * CONCURRENTLY and not when called by DROP INDEX CONCURRENTLY.
+ */
+ WaitForLockers(heaplocktag, AccessExclusiveLock, true);
+
+ /* Finish invalidation of index and mark it as dead */
+ index_concurrently_set_dead(heapId, indexId);
+
+ /*
+ * Again, commit the transaction to make the pg_index update visible
+ * to other sessions.
+ */
+ CommitTransactionCommand();
+ StartTransactionCommand();
+
+ /*
+ * Wait till every transaction that saw the old index state has
+ * finished. See above about progress reporting.
+ */
+ WaitForLockers(heaplocktag, AccessExclusiveLock, true);
+
+ /*
+ * Re-open relations to allow us to complete our actions.
+ *
+ * At this point, nothing should be accessing the index, but lets
+ * leave nothing to chance and grab AccessExclusiveLock on the index
+ * before the physical deletion.
+ */
+ userHeapRelation = table_open(heapId, ShareUpdateExclusiveLock);
+ userIndexRelation = index_open(indexId, AccessExclusiveLock);
+ }
+ else
+ {
+ /* Not concurrent, so just transfer predicate locks and we're good */
+ TransferPredicateLocksToHeapRelation(userIndexRelation);
+ }
+
+ /*
+ * Schedule physical removal of the files (if any)
+ */
+ if (userIndexRelation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
+ RelationDropStorage(userIndexRelation);
+
+ /*
+ * Close and flush the index's relcache entry, to ensure relcache doesn't
+ * try to rebuild it while we're deleting catalog entries. We keep the
+ * lock though.
+ */
+ index_close(userIndexRelation, NoLock);
+
+ RelationForgetRelation(indexId);
+
+ /*
+ * fix INDEX relation, and check for expressional index
+ */
+ indexRelation = table_open(IndexRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for index %u", indexId);
+
+ hasexprs = !heap_attisnull(tuple, Anum_pg_index_indexprs,
+ RelationGetDescr(indexRelation));
+
+ CatalogTupleDelete(indexRelation, &tuple->t_self);
+
+ ReleaseSysCache(tuple);
+ table_close(indexRelation, RowExclusiveLock);
+
+ /*
+ * if it has any expression columns, we might have stored statistics about
+ * them.
+ */
+ if (hasexprs)
+ RemoveStatistics(indexId, 0);
+
+ /*
+ * fix ATTRIBUTE relation
+ */
+ DeleteAttributeTuples(indexId);
+
+ /*
+ * fix RELATION relation
+ */
+ DeleteRelationTuple(indexId);
+
+ /*
+ * fix INHERITS relation
+ */
+ DeleteInheritsTuple(indexId, InvalidOid);
+
+ /*
+ * We are presently too lazy to attempt to compute the new correct value
+ * of relhasindex (the next VACUUM will fix it if necessary). So there is
+ * no need to update the pg_class tuple for the owning relation. But we
+ * must send out a shared-cache-inval notice on the owning relation to
+ * ensure other backends update their relcache lists of indexes. (In the
+ * concurrent case, this is redundant but harmless.)
+ */
+ CacheInvalidateRelcache(userHeapRelation);
+
+ /*
+ * Close owning rel, but keep lock
+ */
+ table_close(userHeapRelation, NoLock);
+
+ /*
+ * Release the session locks before we go.
+ */
+ if (concurrent)
+ {
+ UnlockRelationIdForSession(&heaprelid, ShareUpdateExclusiveLock);
+ UnlockRelationIdForSession(&indexrelid, ShareUpdateExclusiveLock);
+ }
+}
+
+/* ----------------------------------------------------------------
+ * index_build support
+ * ----------------------------------------------------------------
+ */
+
+/* ----------------
+ * BuildIndexInfo
+ * Construct an IndexInfo record for an open index
+ *
+ * IndexInfo stores the information about the index that's needed by
+ * FormIndexDatum, which is used for both index_build() and later insertion
+ * of individual index tuples. Normally we build an IndexInfo for an index
+ * just once per command, and then use it for (potentially) many tuples.
+ * ----------------
+ */
+IndexInfo *
+BuildIndexInfo(Relation index)
+{
+ IndexInfo *ii;
+ Form_pg_index indexStruct = index->rd_index;
+ int i;
+ int numAtts;
+
+ /* check the number of keys, and copy attr numbers into the IndexInfo */
+ numAtts = indexStruct->indnatts;
+ if (numAtts < 1 || numAtts > INDEX_MAX_KEYS)
+ elog(ERROR, "invalid indnatts %d for index %u",
+ numAtts, RelationGetRelid(index));
+
+ /*
+ * Create the node, fetching any expressions needed for expressional
+ * indexes and index predicate if any.
+ */
+ ii = makeIndexInfo(indexStruct->indnatts,
+ indexStruct->indnkeyatts,
+ index->rd_rel->relam,
+ RelationGetIndexExpressions(index),
+ RelationGetIndexPredicate(index),
+ indexStruct->indisunique,
+ indexStruct->indisready,
+ false);
+
+ /* fill in attribute numbers */
+ for (i = 0; i < numAtts; i++)
+ ii->ii_IndexAttrNumbers[i] = indexStruct->indkey.values[i];
+
+ /* fetch exclusion constraint info if any */
+ if (indexStruct->indisexclusion)
+ {
+ RelationGetExclusionInfo(index,
+ &ii->ii_ExclusionOps,
+ &ii->ii_ExclusionProcs,
+ &ii->ii_ExclusionStrats);
+ }
+
+ ii->ii_OpclassOptions = RelationGetIndexRawAttOptions(index);
+
+ return ii;
+}
+
+/* ----------------
+ * BuildDummyIndexInfo
+ * Construct a dummy IndexInfo record for an open index
+ *
+ * This differs from the real BuildIndexInfo in that it will never run any
+ * user-defined code that might exist in index expressions or predicates.
+ * Instead of the real index expressions, we return null constants that have
+ * the right types/typmods/collations. Predicates and exclusion clauses are
+ * just ignored. This is sufficient for the purpose of truncating an index,
+ * since we will not need to actually evaluate the expressions or predicates;
+ * the only thing that's likely to be done with the data is construction of
+ * a tupdesc describing the index's rowtype.
+ * ----------------
+ */
+IndexInfo *
+BuildDummyIndexInfo(Relation index)
+{
+ IndexInfo *ii;
+ Form_pg_index indexStruct = index->rd_index;
+ int i;
+ int numAtts;
+
+ /* check the number of keys, and copy attr numbers into the IndexInfo */
+ numAtts = indexStruct->indnatts;
+ if (numAtts < 1 || numAtts > INDEX_MAX_KEYS)
+ elog(ERROR, "invalid indnatts %d for index %u",
+ numAtts, RelationGetRelid(index));
+
+ /*
+ * Create the node, using dummy index expressions, and pretending there is
+ * no predicate.
+ */
+ ii = makeIndexInfo(indexStruct->indnatts,
+ indexStruct->indnkeyatts,
+ index->rd_rel->relam,
+ RelationGetDummyIndexExpressions(index),
+ NIL,
+ indexStruct->indisunique,
+ indexStruct->indisready,
+ false);
+
+ /* fill in attribute numbers */
+ for (i = 0; i < numAtts; i++)
+ ii->ii_IndexAttrNumbers[i] = indexStruct->indkey.values[i];
+
+ /* We ignore the exclusion constraint if any */
+
+ return ii;
+}
+
+/*
+ * CompareIndexInfo
+ * Return whether the properties of two indexes (in different tables)
+ * indicate that they have the "same" definitions.
+ *
+ * Note: passing collations and opfamilies separately is a kludge. Adding
+ * them to IndexInfo may result in better coding here and elsewhere.
+ *
+ * Use build_attrmap_by_name(index2, index1) to build the attmap.
+ */
+bool
+CompareIndexInfo(IndexInfo *info1, IndexInfo *info2,
+ Oid *collations1, Oid *collations2,
+ Oid *opfamilies1, Oid *opfamilies2,
+ AttrMap *attmap)
+{
+ int i;
+
+ if (info1->ii_Unique != info2->ii_Unique)
+ return false;
+
+ /* indexes are only equivalent if they have the same access method */
+ if (info1->ii_Am != info2->ii_Am)
+ return false;
+
+ /* and same number of attributes */
+ if (info1->ii_NumIndexAttrs != info2->ii_NumIndexAttrs)
+ return false;
+
+ /* and same number of key attributes */
+ if (info1->ii_NumIndexKeyAttrs != info2->ii_NumIndexKeyAttrs)
+ return false;
+
+ /*
+ * and columns match through the attribute map (actual attribute numbers
+ * might differ!) Note that this implies that index columns that are
+ * expressions appear in the same positions. We will next compare the
+ * expressions themselves.
+ */
+ for (i = 0; i < info1->ii_NumIndexAttrs; i++)
+ {
+ if (attmap->maplen < info2->ii_IndexAttrNumbers[i])
+ elog(ERROR, "incorrect attribute map");
+
+ /* ignore expressions at this stage */
+ if ((info1->ii_IndexAttrNumbers[i] != InvalidAttrNumber) &&
+ (attmap->attnums[info2->ii_IndexAttrNumbers[i] - 1] !=
+ info1->ii_IndexAttrNumbers[i]))
+ return false;
+
+ /* collation and opfamily is not valid for including columns */
+ if (i >= info1->ii_NumIndexKeyAttrs)
+ continue;
+
+ if (collations1[i] != collations2[i])
+ return false;
+ if (opfamilies1[i] != opfamilies2[i])
+ return false;
+ }
+
+ /*
+ * For expression indexes: either both are expression indexes, or neither
+ * is; if they are, make sure the expressions match.
+ */
+ if ((info1->ii_Expressions != NIL) != (info2->ii_Expressions != NIL))
+ return false;
+ if (info1->ii_Expressions != NIL)
+ {
+ bool found_whole_row;
+ Node *mapped;
+
+ mapped = map_variable_attnos((Node *) info2->ii_Expressions,
+ 1, 0, attmap,
+ InvalidOid, &found_whole_row);
+ if (found_whole_row)
+ {
+ /*
+ * we could throw an error here, but seems out of scope for this
+ * routine.
+ */
+ return false;
+ }
+
+ if (!equal(info1->ii_Expressions, mapped))
+ return false;
+ }
+
+ /* Partial index predicates must be identical, if they exist */
+ if ((info1->ii_Predicate == NULL) != (info2->ii_Predicate == NULL))
+ return false;
+ if (info1->ii_Predicate != NULL)
+ {
+ bool found_whole_row;
+ Node *mapped;
+
+ mapped = map_variable_attnos((Node *) info2->ii_Predicate,
+ 1, 0, attmap,
+ InvalidOid, &found_whole_row);
+ if (found_whole_row)
+ {
+ /*
+ * we could throw an error here, but seems out of scope for this
+ * routine.
+ */
+ return false;
+ }
+ if (!equal(info1->ii_Predicate, mapped))
+ return false;
+ }
+
+ /* No support currently for comparing exclusion indexes. */
+ if (info1->ii_ExclusionOps != NULL || info2->ii_ExclusionOps != NULL)
+ return false;
+
+ return true;
+}
+
+/* ----------------
+ * BuildSpeculativeIndexInfo
+ * Add extra state to IndexInfo record
+ *
+ * For unique indexes, we usually don't want to add info to the IndexInfo for
+ * checking uniqueness, since the B-Tree AM handles that directly. However,
+ * in the case of speculative insertion, additional support is required.
+ *
+ * Do this processing here rather than in BuildIndexInfo() to not incur the
+ * overhead in the common non-speculative cases.
+ * ----------------
+ */
+void
+BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
+{
+ int indnkeyatts;
+ int i;
+
+ indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index);
+
+ /*
+ * fetch info for checking unique indexes
+ */
+ Assert(ii->ii_Unique);
+
+ if (index->rd_rel->relam != BTREE_AM_OID)
+ elog(ERROR, "unexpected non-btree speculative unique index");
+
+ ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
+ ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
+ ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
+
+ /*
+ * We have to look up the operator's strategy number. This provides a
+ * cross-check that the operator does match the index.
+ */
+ /* We need the func OIDs and strategy numbers too */
+ for (i = 0; i < indnkeyatts; i++)
+ {
+ ii->ii_UniqueStrats[i] = BTEqualStrategyNumber;
+ ii->ii_UniqueOps[i] =
+ get_opfamily_member(index->rd_opfamily[i],
+ index->rd_opcintype[i],
+ index->rd_opcintype[i],
+ ii->ii_UniqueStrats[i]);
+ if (!OidIsValid(ii->ii_UniqueOps[i]))
+ elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
+ ii->ii_UniqueStrats[i], index->rd_opcintype[i],
+ index->rd_opcintype[i], index->rd_opfamily[i]);
+ ii->ii_UniqueProcs[i] = get_opcode(ii->ii_UniqueOps[i]);
+ }
+}
+
+/* ----------------
+ * FormIndexDatum
+ * Construct values[] and isnull[] arrays for a new index tuple.
+ *
+ * indexInfo Info about the index
+ * slot Heap tuple for which we must prepare an index entry
+ * estate executor state for evaluating any index expressions
+ * values Array of index Datums (output area)
+ * isnull Array of is-null indicators (output area)
+ *
+ * When there are no index expressions, estate may be NULL. Otherwise it
+ * must be supplied, *and* the ecxt_scantuple slot of its per-tuple expr
+ * context must point to the heap tuple passed in.
+ *
+ * Notice we don't actually call index_form_tuple() here; we just prepare
+ * its input arrays values[] and isnull[]. This is because the index AM
+ * may wish to alter the data before storage.
+ * ----------------
+ */
+void
+FormIndexDatum(IndexInfo *indexInfo,
+ TupleTableSlot *slot,
+ EState *estate,
+ Datum *values,
+ bool *isnull)
+{
+ ListCell *indexpr_item;
+ int i;
+
+ if (indexInfo->ii_Expressions != NIL &&
+ indexInfo->ii_ExpressionsState == NIL)
+ {
+ /* First time through, set up expression evaluation state */
+ indexInfo->ii_ExpressionsState =
+ ExecPrepareExprList(indexInfo->ii_Expressions, estate);
+ /* Check caller has set up context correctly */
+ Assert(GetPerTupleExprContext(estate)->ecxt_scantuple == slot);
+ }
+ indexpr_item = list_head(indexInfo->ii_ExpressionsState);
+
+ for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+ {
+ int keycol = indexInfo->ii_IndexAttrNumbers[i];
+ Datum iDatum;
+ bool isNull;
+
+ if (keycol < 0)
+ iDatum = slot_getsysattr(slot, keycol, &isNull);
+ else if (keycol != 0)
+ {
+ /*
+ * Plain index column; get the value we need directly from the
+ * heap tuple.
+ */
+ iDatum = slot_getattr(slot, keycol, &isNull);
+ }
+ else
+ {
+ /*
+ * Index expression --- need to evaluate it.
+ */
+ if (indexpr_item == NULL)
+ elog(ERROR, "wrong number of index expressions");
+ iDatum = ExecEvalExprSwitchContext((ExprState *) lfirst(indexpr_item),
+ GetPerTupleExprContext(estate),
+ &isNull);
+ indexpr_item = lnext(indexInfo->ii_ExpressionsState, indexpr_item);
+ }
+ values[i] = iDatum;
+ isnull[i] = isNull;
+ }
+
+ if (indexpr_item != NULL)
+ elog(ERROR, "wrong number of index expressions");
+}
+
+
+/*
+ * index_update_stats --- update pg_class entry after CREATE INDEX or REINDEX
+ *
+ * This routine updates the pg_class row of either an index or its parent
+ * relation after CREATE INDEX or REINDEX. Its rather bizarre API is designed
+ * to ensure we can do all the necessary work in just one update.
+ *
+ * hasindex: set relhasindex to this value
+ * reltuples: if >= 0, set reltuples to this value; else no change
+ *
+ * If reltuples >= 0, relpages and relallvisible are also updated (using
+ * RelationGetNumberOfBlocks() and visibilitymap_count()).
+ *
+ * NOTE: an important side-effect of this operation is that an SI invalidation
+ * message is sent out to all backends --- including me --- causing relcache
+ * entries to be flushed or updated with the new data. This must happen even
+ * if we find that no change is needed in the pg_class row. When updating
+ * a heap entry, this ensures that other backends find out about the new
+ * index. When updating an index, it's important because some index AMs
+ * expect a relcache flush to occur after REINDEX.
+ */
+static void
+index_update_stats(Relation rel,
+ bool hasindex,
+ double reltuples)
+{
+ Oid relid = RelationGetRelid(rel);
+ Relation pg_class;
+ HeapTuple tuple;
+ Form_pg_class rd_rel;
+ bool dirty;
+
+ /*
+ * We always update the pg_class row using a non-transactional,
+ * overwrite-in-place update. There are several reasons for this:
+ *
+ * 1. In bootstrap mode, we have no choice --- UPDATE wouldn't work.
+ *
+ * 2. We could be reindexing pg_class itself, in which case we can't move
+ * its pg_class row because CatalogTupleInsert/CatalogTupleUpdate might
+ * not know about all the indexes yet (see reindex_relation).
+ *
+ * 3. Because we execute CREATE INDEX with just share lock on the parent
+ * rel (to allow concurrent index creations), an ordinary update could
+ * suffer a tuple-concurrently-updated failure against another CREATE
+ * INDEX committing at about the same time. We can avoid that by having
+ * them both do nontransactional updates (we assume they will both be
+ * trying to change the pg_class row to the same thing, so it doesn't
+ * matter which goes first).
+ *
+ * It is safe to use a non-transactional update even though our
+ * transaction could still fail before committing. Setting relhasindex
+ * true is safe even if there are no indexes (VACUUM will eventually fix
+ * it). And of course the new relpages and reltuples counts are correct
+ * regardless. However, we don't want to change relpages (or
+ * relallvisible) if the caller isn't providing an updated reltuples
+ * count, because that would bollix the reltuples/relpages ratio which is
+ * what's really important.
+ */
+
+ pg_class = table_open(RelationRelationId, RowExclusiveLock);
+
+ /*
+ * Make a copy of the tuple to update. Normally we use the syscache, but
+ * we can't rely on that during bootstrap or while reindexing pg_class
+ * itself.
+ */
+ if (IsBootstrapProcessingMode() ||
+ ReindexIsProcessingHeap(RelationRelationId))
+ {
+ /* don't assume syscache will work */
+ TableScanDesc pg_class_scan;
+ ScanKeyData key[1];
+
+ ScanKeyInit(&key[0],
+ Anum_pg_class_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+
+ pg_class_scan = table_beginscan_catalog(pg_class, 1, key);
+ tuple = heap_getnext(pg_class_scan, ForwardScanDirection);
+ tuple = heap_copytuple(tuple);
+ table_endscan(pg_class_scan);
+ }
+ else
+ {
+ /* normal case, use syscache */
+ tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
+ }
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "could not find tuple for relation %u", relid);
+ rd_rel = (Form_pg_class) GETSTRUCT(tuple);
+
+ /* Should this be a more comprehensive test? */
+ Assert(rd_rel->relkind != RELKIND_PARTITIONED_INDEX);
+
+ /* Apply required updates, if any, to copied tuple */
+
+ dirty = false;
+ if (rd_rel->relhasindex != hasindex)
+ {
+ rd_rel->relhasindex = hasindex;
+ dirty = true;
+ }
+
+ if (reltuples >= 0)
+ {
+ BlockNumber relpages = RelationGetNumberOfBlocks(rel);
+ BlockNumber relallvisible;
+
+ if (rd_rel->relkind != RELKIND_INDEX)
+ visibilitymap_count(rel, &relallvisible, NULL);
+ else /* don't bother for indexes */
+ relallvisible = 0;
+
+ if (rd_rel->relpages != (int32) relpages)
+ {
+ rd_rel->relpages = (int32) relpages;
+ dirty = true;
+ }
+ if (rd_rel->reltuples != (float4) reltuples)
+ {
+ rd_rel->reltuples = (float4) reltuples;
+ dirty = true;
+ }
+ if (rd_rel->relallvisible != (int32) relallvisible)
+ {
+ rd_rel->relallvisible = (int32) relallvisible;
+ dirty = true;
+ }
+ }
+
+ /*
+ * If anything changed, write out the tuple
+ */
+ if (dirty)
+ {
+ heap_inplace_update(pg_class, tuple);
+ /* the above sends a cache inval message */
+ }
+ else
+ {
+ /* no need to change tuple, but force relcache inval anyway */
+ CacheInvalidateRelcacheByTuple(tuple);
+ }
+
+ heap_freetuple(tuple);
+
+ table_close(pg_class, RowExclusiveLock);
+}
+
+
+/*
+ * index_build - invoke access-method-specific index build procedure
+ *
+ * On entry, the index's catalog entries are valid, and its physical disk
+ * file has been created but is empty. We call the AM-specific build
+ * procedure to fill in the index contents. We then update the pg_class
+ * entries of the index and heap relation as needed, using statistics
+ * returned by ambuild as well as data passed by the caller.
+ *
+ * isreindex indicates we are recreating a previously-existing index.
+ * parallel indicates if parallelism may be useful.
+ *
+ * Note: before Postgres 8.2, the passed-in heap and index Relations
+ * were automatically closed by this routine. This is no longer the case.
+ * The caller opened 'em, and the caller should close 'em.
+ */
+void
+index_build(Relation heapRelation,
+ Relation indexRelation,
+ IndexInfo *indexInfo,
+ bool isreindex,
+ bool parallel)
+{
+ IndexBuildResult *stats;
+ Oid save_userid;
+ int save_sec_context;
+ int save_nestlevel;
+
+ /*
+ * sanity checks
+ */
+ Assert(RelationIsValid(indexRelation));
+ Assert(PointerIsValid(indexRelation->rd_indam));
+ Assert(PointerIsValid(indexRelation->rd_indam->ambuild));
+ Assert(PointerIsValid(indexRelation->rd_indam->ambuildempty));
+
+ /*
+ * Determine worker process details for parallel CREATE INDEX. Currently,
+ * only btree has support for parallel builds.
+ *
+ * Note that planner considers parallel safety for us.
+ */
+ if (parallel && IsNormalProcessingMode() &&
+ indexRelation->rd_rel->relam == BTREE_AM_OID)
+ indexInfo->ii_ParallelWorkers =
+ plan_create_index_workers(RelationGetRelid(heapRelation),
+ RelationGetRelid(indexRelation));
+
+ if (indexInfo->ii_ParallelWorkers == 0)
+ ereport(DEBUG1,
+ (errmsg("building index \"%s\" on table \"%s\" serially",
+ RelationGetRelationName(indexRelation),
+ RelationGetRelationName(heapRelation))));
+ else
+ ereport(DEBUG1,
+ (errmsg_plural("building index \"%s\" on table \"%s\" with request for %d parallel worker",
+ "building index \"%s\" on table \"%s\" with request for %d parallel workers",
+ indexInfo->ii_ParallelWorkers,
+ RelationGetRelationName(indexRelation),
+ RelationGetRelationName(heapRelation),
+ indexInfo->ii_ParallelWorkers)));
+
+ /*
+ * Switch to the table owner's userid, so that any index functions are run
+ * as that user. Also lock down security-restricted operations and
+ * arrange to make GUC variable changes local to this command.
+ */
+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
+ SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
+ save_nestlevel = NewGUCNestLevel();
+
+ /* Set up initial progress report status */
+ {
+ const int index[] = {
+ PROGRESS_CREATEIDX_PHASE,
+ PROGRESS_CREATEIDX_SUBPHASE,
+ PROGRESS_CREATEIDX_TUPLES_DONE,
+ PROGRESS_CREATEIDX_TUPLES_TOTAL,
+ PROGRESS_SCAN_BLOCKS_DONE,
+ PROGRESS_SCAN_BLOCKS_TOTAL
+ };
+ const int64 val[] = {
+ PROGRESS_CREATEIDX_PHASE_BUILD,
+ PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE,
+ 0, 0, 0, 0
+ };
+
+ pgstat_progress_update_multi_param(6, index, val);
+ }
+
+ /*
+ * Call the access method's build procedure
+ */
+ stats = indexRelation->rd_indam->ambuild(heapRelation, indexRelation,
+ indexInfo);
+ Assert(PointerIsValid(stats));
+
+ /*
+ * If this is an unlogged index, we may need to write out an init fork for
+ * it -- but we must first check whether one already exists. If, for
+ * example, an unlogged relation is truncated in the transaction that
+ * created it, or truncated twice in a subsequent transaction, the
+ * relfilenode won't change, and nothing needs to be done here.
+ */
+ if (indexRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
+ !smgrexists(indexRelation->rd_smgr, INIT_FORKNUM))
+ {
+ RelationOpenSmgr(indexRelation);
+ smgrcreate(indexRelation->rd_smgr, INIT_FORKNUM, false);
+ indexRelation->rd_indam->ambuildempty(indexRelation);
+ }
+
+ /*
+ * If we found any potentially broken HOT chains, mark the index as not
+ * being usable until the current transaction is below the event horizon.
+ * See src/backend/access/heap/README.HOT for discussion. Also set this
+ * if early pruning/vacuuming is enabled for the heap relation. While it
+ * might become safe to use the index earlier based on actual cleanup
+ * activity and other active transactions, the test for that would be much
+ * more complex and would require some form of blocking, so keep it simple
+ * and fast by just using the current transaction.
+ *
+ * However, when reindexing an existing index, we should do nothing here.
+ * Any HOT chains that are broken with respect to the index must predate
+ * the index's original creation, so there is no need to change the
+ * index's usability horizon. Moreover, we *must not* try to change the
+ * index's pg_index entry while reindexing pg_index itself, and this
+ * optimization nicely prevents that. The more complex rules needed for a
+ * reindex are handled separately after this function returns.
+ *
+ * We also need not set indcheckxmin during a concurrent index build,
+ * because we won't set indisvalid true until all transactions that care
+ * about the broken HOT chains or early pruning/vacuuming are gone.
+ *
+ * Therefore, this code path can only be taken during non-concurrent
+ * CREATE INDEX. Thus the fact that heap_update will set the pg_index
+ * tuple's xmin doesn't matter, because that tuple was created in the
+ * current transaction anyway. That also means we don't need to worry
+ * about any concurrent readers of the tuple; no other transaction can see
+ * it yet.
+ */
+ if ((indexInfo->ii_BrokenHotChain || EarlyPruningEnabled(heapRelation)) &&
+ !isreindex &&
+ !indexInfo->ii_Concurrent)
+ {
+ Oid indexId = RelationGetRelid(indexRelation);
+ Relation pg_index;
+ HeapTuple indexTuple;
+ Form_pg_index indexForm;
+
+ pg_index = table_open(IndexRelationId, RowExclusiveLock);
+
+ indexTuple = SearchSysCacheCopy1(INDEXRELID,
+ ObjectIdGetDatum(indexId));
+ if (!HeapTupleIsValid(indexTuple))
+ elog(ERROR, "cache lookup failed for index %u", indexId);
+ indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
+
+ /* If it's a new index, indcheckxmin shouldn't be set ... */
+ Assert(!indexForm->indcheckxmin);
+
+ indexForm->indcheckxmin = true;
+ CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
+
+ heap_freetuple(indexTuple);
+ table_close(pg_index, RowExclusiveLock);
+ }
+
+ /*
+ * Update heap and index pg_class rows
+ */
+ index_update_stats(heapRelation,
+ true,
+ stats->heap_tuples);
+
+ index_update_stats(indexRelation,
+ false,
+ stats->index_tuples);
+
+ /* Make the updated catalog row versions visible */
+ CommandCounterIncrement();
+
+ /*
+ * If it's for an exclusion constraint, make a second pass over the heap
+ * to verify that the constraint is satisfied. We must not do this until
+ * the index is fully valid. (Broken HOT chains shouldn't matter, though;
+ * see comments for IndexCheckExclusion.)
+ */
+ if (indexInfo->ii_ExclusionOps != NULL)
+ IndexCheckExclusion(heapRelation, indexRelation, indexInfo);
+
+ /* Roll back any GUC changes executed by index functions */
+ AtEOXact_GUC(false, save_nestlevel);
+
+ /* Restore userid and security context */
+ SetUserIdAndSecContext(save_userid, save_sec_context);
+}
+
+/*
+ * IndexCheckExclusion - verify that a new exclusion constraint is satisfied
+ *
+ * When creating an exclusion constraint, we first build the index normally
+ * and then rescan the heap to check for conflicts. We assume that we only
+ * need to validate tuples that are live according to an up-to-date snapshot,
+ * and that these were correctly indexed even in the presence of broken HOT
+ * chains. This should be OK since we are holding at least ShareLock on the
+ * table, meaning there can be no uncommitted updates from other transactions.
+ * (Note: that wouldn't necessarily work for system catalogs, since many
+ * operations release write lock early on the system catalogs.)
+ */
+static void
+IndexCheckExclusion(Relation heapRelation,
+ Relation indexRelation,
+ IndexInfo *indexInfo)
+{
+ TableScanDesc scan;
+ Datum values[INDEX_MAX_KEYS];
+ bool isnull[INDEX_MAX_KEYS];
+ ExprState *predicate;
+ TupleTableSlot *slot;
+ EState *estate;
+ ExprContext *econtext;
+ Snapshot snapshot;
+
+ /*
+ * If we are reindexing the target index, mark it as no longer being
+ * reindexed, to forestall an Assert in index_beginscan when we try to use
+ * the index for probes. This is OK because the index is now fully valid.
+ */
+ if (ReindexIsCurrentlyProcessingIndex(RelationGetRelid(indexRelation)))
+ ResetReindexProcessing();
+
+ /*
+ * Need an EState for evaluation of index expressions and partial-index
+ * predicates. Also a slot to hold the current tuple.
+ */
+ estate = CreateExecutorState();
+ econtext = GetPerTupleExprContext(estate);
+ slot = table_slot_create(heapRelation, NULL);
+
+ /* Arrange for econtext's scan tuple to be the tuple under test */
+ econtext->ecxt_scantuple = slot;
+
+ /* Set up execution state for predicate, if any. */
+ predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
+
+ /*
+ * Scan all live tuples in the base relation.
+ */
+ snapshot = RegisterSnapshot(GetLatestSnapshot());
+ scan = table_beginscan_strat(heapRelation, /* relation */
+ snapshot, /* snapshot */
+ 0, /* number of keys */
+ NULL, /* scan key */
+ true, /* buffer access strategy OK */
+ true); /* syncscan OK */
+
+ while (table_scan_getnextslot(scan, ForwardScanDirection, slot))
+ {
+ CHECK_FOR_INTERRUPTS();
+
+ /*
+ * In a partial index, ignore tuples that don't satisfy the predicate.
+ */
+ if (predicate != NULL)
+ {
+ if (!ExecQual(predicate, econtext))
+ continue;
+ }
+
+ /*
+ * Extract index column values, including computing expressions.
+ */
+ FormIndexDatum(indexInfo,
+ slot,
+ estate,
+ values,
+ isnull);
+
+ /*
+ * Check that this tuple has no conflicts.
+ */
+ check_exclusion_constraint(heapRelation,
+ indexRelation, indexInfo,
+ &(slot->tts_tid), values, isnull,
+ estate, true);
+
+ MemoryContextReset(econtext->ecxt_per_tuple_memory);
+ }
+
+ table_endscan(scan);
+ UnregisterSnapshot(snapshot);
+
+ ExecDropSingleTupleTableSlot(slot);
+
+ FreeExecutorState(estate);
+
+ /* These may have been pointing to the now-gone estate */
+ indexInfo->ii_ExpressionsState = NIL;
+ indexInfo->ii_PredicateState = NULL;
+}
+
+
+/*
+ * validate_index - support code for concurrent index builds
+ *
+ * We do a concurrent index build by first inserting the catalog entry for the
+ * index via index_create(), marking it not indisready and not indisvalid.
+ * Then we commit our transaction and start a new one, then we wait for all
+ * transactions that could have been modifying the table to terminate. Now
+ * we know that any subsequently-started transactions will see the index and
+ * honor its constraints on HOT updates; so while existing HOT-chains might
+ * be broken with respect to the index, no currently live tuple will have an
+ * incompatible HOT update done to it. We now build the index normally via
+ * index_build(), while holding a weak lock that allows concurrent
+ * insert/update/delete. Also, we index only tuples that are valid
+ * as of the start of the scan (see table_index_build_scan), whereas a normal
+ * build takes care to include recently-dead tuples. This is OK because
+ * we won't mark the index valid until all transactions that might be able
+ * to see those tuples are gone. The reason for doing that is to avoid
+ * bogus unique-index failures due to concurrent UPDATEs (we might see
+ * different versions of the same row as being valid when we pass over them,
+ * if we used HeapTupleSatisfiesVacuum). This leaves us with an index that
+ * does not contain any tuples added to the table while we built the index.
+ *
+ * Next, we mark the index "indisready" (but still not "indisvalid") and
+ * commit the second transaction and start a third. Again we wait for all
+ * transactions that could have been modifying the table to terminate. Now
+ * we know that any subsequently-started transactions will see the index and
+ * insert their new tuples into it. We then take a new reference snapshot
+ * which is passed to validate_index(). Any tuples that are valid according
+ * to this snap, but are not in the index, must be added to the index.
+ * (Any tuples committed live after the snap will be inserted into the
+ * index by their originating transaction. Any tuples committed dead before
+ * the snap need not be indexed, because we will wait out all transactions
+ * that might care about them before we mark the index valid.)
+ *
+ * validate_index() works by first gathering all the TIDs currently in the
+ * index, using a bulkdelete callback that just stores the TIDs and doesn't
+ * ever say "delete it". (This should be faster than a plain indexscan;
+ * also, not all index AMs support full-index indexscan.) Then we sort the
+ * TIDs, and finally scan the table doing a "merge join" against the TID list
+ * to see which tuples are missing from the index. Thus we will ensure that
+ * all tuples valid according to the reference snapshot are in the index.
+ *
+ * Building a unique index this way is tricky: we might try to insert a
+ * tuple that is already dead or is in process of being deleted, and we
+ * mustn't have a uniqueness failure against an updated version of the same
+ * row. We could try to check the tuple to see if it's already dead and tell
+ * index_insert() not to do the uniqueness check, but that still leaves us
+ * with a race condition against an in-progress update. To handle that,
+ * we expect the index AM to recheck liveness of the to-be-inserted tuple
+ * before it declares a uniqueness error.
+ *
+ * After completing validate_index(), we wait until all transactions that
+ * were alive at the time of the reference snapshot are gone; this is
+ * necessary to be sure there are none left with a transaction snapshot
+ * older than the reference (and hence possibly able to see tuples we did
+ * not index). Then we mark the index "indisvalid" and commit. Subsequent
+ * transactions will be able to use it for queries.
+ *
+ * Doing two full table scans is a brute-force strategy. We could try to be
+ * cleverer, eg storing new tuples in a special area of the table (perhaps
+ * making the table append-only by setting use_fsm). However that would
+ * add yet more locking issues.
+ */
+void
+validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
+{
+ Relation heapRelation,
+ indexRelation;
+ IndexInfo *indexInfo;
+ IndexVacuumInfo ivinfo;
+ ValidateIndexState state;
+ Oid save_userid;
+ int save_sec_context;
+ int save_nestlevel;
+
+ {
+ const int index[] = {
+ PROGRESS_CREATEIDX_PHASE,
+ PROGRESS_CREATEIDX_TUPLES_DONE,
+ PROGRESS_CREATEIDX_TUPLES_TOTAL,
+ PROGRESS_SCAN_BLOCKS_DONE,
+ PROGRESS_SCAN_BLOCKS_TOTAL
+ };
+ const int64 val[] = {
+ PROGRESS_CREATEIDX_PHASE_VALIDATE_IDXSCAN,
+ 0, 0, 0, 0
+ };
+
+ pgstat_progress_update_multi_param(5, index, val);
+ }
+
+ /* Open and lock the parent heap relation */
+ heapRelation = table_open(heapId, ShareUpdateExclusiveLock);
+ /* And the target index relation */
+ indexRelation = index_open(indexId, RowExclusiveLock);
+
+ /*
+ * Fetch info needed for index_insert. (You might think this should be
+ * passed in from DefineIndex, but its copy is long gone due to having
+ * been built in a previous transaction.)
+ */
+ indexInfo = BuildIndexInfo(indexRelation);
+
+ /* mark build is concurrent just for consistency */
+ indexInfo->ii_Concurrent = true;
+
+ /*
+ * Switch to the table owner's userid, so that any index functions are run
+ * as that user. Also lock down security-restricted operations and
+ * arrange to make GUC variable changes local to this command.
+ */
+ GetUserIdAndSecContext(&save_userid, &save_sec_context);
+ SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
+ save_sec_context | SECURITY_RESTRICTED_OPERATION);
+ save_nestlevel = NewGUCNestLevel();
+
+ /*
+ * Scan the index and gather up all the TIDs into a tuplesort object.
+ */
+ ivinfo.index = indexRelation;
+ ivinfo.analyze_only = false;
+ ivinfo.report_progress = true;
+ ivinfo.estimated_count = true;
+ ivinfo.message_level = DEBUG2;
+ ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
+ ivinfo.strategy = NULL;
+
+ /*
+ * Encode TIDs as int8 values for the sort, rather than directly sorting
+ * item pointers. This can be significantly faster, primarily because TID
+ * is a pass-by-reference type on all platforms, whereas int8 is
+ * pass-by-value on most platforms.
+ */
+ state.tuplesort = tuplesort_begin_datum(INT8OID, Int8LessOperator,
+ InvalidOid, false,
+ maintenance_work_mem,
+ NULL, false);
+ state.htups = state.itups = state.tups_inserted = 0;
+
+ /* ambulkdelete updates progress metrics */
+ (void) index_bulk_delete(&ivinfo, NULL,
+ validate_index_callback, (void *) &state);
+
+ /* Execute the sort */
+ {
+ const int index[] = {
+ PROGRESS_CREATEIDX_PHASE,
+ PROGRESS_SCAN_BLOCKS_DONE,
+ PROGRESS_SCAN_BLOCKS_TOTAL
+ };
+ const int64 val[] = {
+ PROGRESS_CREATEIDX_PHASE_VALIDATE_SORT,
+ 0, 0
+ };
+
+ pgstat_progress_update_multi_param(3, index, val);
+ }
+ tuplesort_performsort(state.tuplesort);
+
+ /*
+ * Now scan the heap and "merge" it with the index
+ */
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_PHASE,
+ PROGRESS_CREATEIDX_PHASE_VALIDATE_TABLESCAN);
+ table_index_validate_scan(heapRelation,
+ indexRelation,
+ indexInfo,
+ snapshot,
+ &state);
+
+ /* Done with tuplesort object */
+ tuplesort_end(state.tuplesort);
+
+ elog(DEBUG2,
+ "validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
+ state.htups, state.itups, state.tups_inserted);
+
+ /* Roll back any GUC changes executed by index functions */
+ AtEOXact_GUC(false, save_nestlevel);
+
+ /* Restore userid and security context */
+ SetUserIdAndSecContext(save_userid, save_sec_context);
+
+ /* Close rels, but keep locks */
+ index_close(indexRelation, NoLock);
+ table_close(heapRelation, NoLock);
+}
+
+/*
+ * validate_index_callback - bulkdelete callback to collect the index TIDs
+ */
+static bool
+validate_index_callback(ItemPointer itemptr, void *opaque)
+{
+ ValidateIndexState *state = (ValidateIndexState *) opaque;
+ int64 encoded = itemptr_encode(itemptr);
+
+ tuplesort_putdatum(state->tuplesort, Int64GetDatum(encoded), false);
+ state->itups += 1;
+ return false; /* never actually delete anything */
+}
+
+/*
+ * index_set_state_flags - adjust pg_index state flags
+ *
+ * This is used during CREATE/DROP INDEX CONCURRENTLY to adjust the pg_index
+ * flags that denote the index's state.
+ *
+ * Note that CatalogTupleUpdate() sends a cache invalidation message for the
+ * tuple, so other sessions will hear about the update as soon as we commit.
+ */
+void
+index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
+{
+ Relation pg_index;
+ HeapTuple indexTuple;
+ Form_pg_index indexForm;
+
+ /* Open pg_index and fetch a writable copy of the index's tuple */
+ pg_index = table_open(IndexRelationId, RowExclusiveLock);
+
+ indexTuple = SearchSysCacheCopy1(INDEXRELID,
+ ObjectIdGetDatum(indexId));
+ if (!HeapTupleIsValid(indexTuple))
+ elog(ERROR, "cache lookup failed for index %u", indexId);
+ indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
+
+ /* Perform the requested state change on the copy */
+ switch (action)
+ {
+ case INDEX_CREATE_SET_READY:
+ /* Set indisready during a CREATE INDEX CONCURRENTLY sequence */
+ Assert(indexForm->indislive);
+ Assert(!indexForm->indisready);
+ Assert(!indexForm->indisvalid);
+ indexForm->indisready = true;
+ break;
+ case INDEX_CREATE_SET_VALID:
+ /* Set indisvalid during a CREATE INDEX CONCURRENTLY sequence */
+ Assert(indexForm->indislive);
+ Assert(indexForm->indisready);
+ Assert(!indexForm->indisvalid);
+ indexForm->indisvalid = true;
+ break;
+ case INDEX_DROP_CLEAR_VALID:
+
+ /*
+ * Clear indisvalid during a DROP INDEX CONCURRENTLY sequence
+ *
+ * If indisready == true we leave it set so the index still gets
+ * maintained by active transactions. We only need to ensure that
+ * indisvalid is false. (We don't assert that either is initially
+ * true, though, since we want to be able to retry a DROP INDEX
+ * CONCURRENTLY that failed partway through.)
+ *
+ * Note: the CLUSTER logic assumes that indisclustered cannot be
+ * set on any invalid index, so clear that flag too.
+ */
+ indexForm->indisvalid = false;
+ indexForm->indisclustered = false;
+ break;
+ case INDEX_DROP_SET_DEAD:
+
+ /*
+ * Clear indisready/indislive during DROP INDEX CONCURRENTLY
+ *
+ * We clear both indisready and indislive, because we not only
+ * want to stop updates, we want to prevent sessions from touching
+ * the index at all.
+ */
+ Assert(!indexForm->indisvalid);
+ indexForm->indisready = false;
+ indexForm->indislive = false;
+ break;
+ }
+
+ /* ... and update it */
+ CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
+
+ table_close(pg_index, RowExclusiveLock);
+}
+
+
+/*
+ * IndexGetRelation: given an index's relation OID, get the OID of the
+ * relation it is an index on. Uses the system cache.
+ */
+Oid
+IndexGetRelation(Oid indexId, bool missing_ok)
+{
+ HeapTuple tuple;
+ Form_pg_index index;
+ Oid result;
+
+ tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexId));
+ if (!HeapTupleIsValid(tuple))
+ {
+ if (missing_ok)
+ return InvalidOid;
+ elog(ERROR, "cache lookup failed for index %u", indexId);
+ }
+ index = (Form_pg_index) GETSTRUCT(tuple);
+ Assert(index->indexrelid == indexId);
+
+ result = index->indrelid;
+ ReleaseSysCache(tuple);
+ return result;
+}
+
+/*
+ * reindex_index - This routine is used to recreate a single index
+ */
+void
+reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
+ int options)
+{
+ Relation iRel,
+ heapRelation;
+ Oid heapId;
+ IndexInfo *indexInfo;
+ volatile bool skipped_constraint = false;
+ PGRUsage ru0;
+ bool progress = (options & REINDEXOPT_REPORT_PROGRESS) != 0;
+
+ pg_rusage_init(&ru0);
+
+ /*
+ * Open and lock the parent heap relation. ShareLock is sufficient since
+ * we only need to be sure no schema or data changes are going on.
+ */
+ heapId = IndexGetRelation(indexId, false);
+ heapRelation = table_open(heapId, ShareLock);
+
+ if (progress)
+ {
+ pgstat_progress_start_command(PROGRESS_COMMAND_CREATE_INDEX,
+ heapId);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_COMMAND,
+ PROGRESS_CREATEIDX_COMMAND_REINDEX);
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_INDEX_OID,
+ indexId);
+ }
+
+ /*
+ * Open the target index relation and get an exclusive lock on it, to
+ * ensure that no one else is touching this particular index.
+ */
+ iRel = index_open(indexId, AccessExclusiveLock);
+
+ if (progress)
+ pgstat_progress_update_param(PROGRESS_CREATEIDX_ACCESS_METHOD_OID,
+ iRel->rd_rel->relam);
+
+ /*
+ * The case of reindexing partitioned tables and indexes is handled
+ * differently by upper layers, so this case shouldn't arise.
+ */
+ if (iRel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
+ elog(ERROR, "unsupported relation kind for index \"%s\"",
+ RelationGetRelationName(iRel));
+
+ /*
+ * Don't allow reindex on temp tables of other backends ... their local
+ * buffer manager is not going to cope.
+ */
+ if (RELATION_IS_OTHER_TEMP(iRel))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot reindex temporary tables of other sessions")));
+
+ /*
+ * Don't allow reindex of an invalid index on TOAST table. This is a
+ * leftover from a failed REINDEX CONCURRENTLY, and if rebuilt it would
+ * not be possible to drop it anymore.
+ */
+ if (IsToastNamespace(RelationGetNamespace(iRel)) &&
+ !get_index_isvalid(indexId))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot reindex invalid index on TOAST table")));
+
+ /*
+ * Also check for active uses of the index in the current transaction; we
+ * don't want to reindex underneath an open indexscan.
+ */
+ CheckTableNotInUse(iRel, "REINDEX INDEX");
+
+ /*
+ * All predicate locks on the index are about to be made invalid. Promote
+ * them to relation locks on the heap.
+ */
+ TransferPredicateLocksToHeapRelation(iRel);
+
+ /* Fetch info needed for index_build */
+ indexInfo = BuildIndexInfo(iRel);
+
+ /* If requested, skip checking uniqueness/exclusion constraints */
+ if (skip_constraint_checks)
+ {
+ if (indexInfo->ii_Unique || indexInfo->ii_ExclusionOps != NULL)
+ skipped_constraint = true;
+ indexInfo->ii_Unique = false;
+ indexInfo->ii_ExclusionOps = NULL;
+ indexInfo->ii_ExclusionProcs = NULL;
+ indexInfo->ii_ExclusionStrats = NULL;
+ }
+
+ /* Suppress use of the target index while rebuilding it */
+ SetReindexProcessing(heapId, indexId);
+
+ /* Create a new physical relation for the index */
+ RelationSetNewRelfilenode(iRel, persistence);
+
+ /* Initialize the index and rebuild */
+ /* Note: we do not need to re-establish pkey setting */
+ index_build(heapRelation, iRel, indexInfo, true, true);
+
+ /* Re-allow use of target index */
+ ResetReindexProcessing();
+
+ /*
+ * If the index is marked invalid/not-ready/dead (ie, it's from a failed
+ * CREATE INDEX CONCURRENTLY, or a DROP INDEX CONCURRENTLY failed midway),
+ * and we didn't skip a uniqueness check, we can now mark it valid. This
+ * allows REINDEX to be used to clean up in such cases.
+ *
+ * We can also reset indcheckxmin, because we have now done a
+ * non-concurrent index build, *except* in the case where index_build
+ * found some still-broken HOT chains. If it did, and we don't have to
+ * change any of the other flags, we just leave indcheckxmin alone (note
+ * that index_build won't have changed it, because this is a reindex).
+ * This is okay and desirable because not updating the tuple leaves the
+ * index's usability horizon (recorded as the tuple's xmin value) the same
+ * as it was.
+ *
+ * But, if the index was invalid/not-ready/dead and there were broken HOT
+ * chains, we had better force indcheckxmin true, because the normal
+ * argument that the HOT chains couldn't conflict with the index is
+ * suspect for an invalid index. (A conflict is definitely possible if
+ * the index was dead. It probably shouldn't happen otherwise, but let's
+ * be conservative.) In this case advancing the usability horizon is
+ * appropriate.
+ *
+ * Another reason for avoiding unnecessary updates here is that while
+ * reindexing pg_index itself, we must not try to update tuples in it.
+ * pg_index's indexes should always have these flags in their clean state,
+ * so that won't happen.
+ *
+ * If early pruning/vacuuming is enabled for the heap relation, the
+ * usability horizon must be advanced to the current transaction on every
+ * build or rebuild. pg_index is OK in this regard because catalog tables
+ * are not subject to early cleanup.
+ */
+ if (!skipped_constraint)
+ {
+ Relation pg_index;
+ HeapTuple indexTuple;
+ Form_pg_index indexForm;
+ bool index_bad;
+ bool early_pruning_enabled = EarlyPruningEnabled(heapRelation);
+
+ pg_index = table_open(IndexRelationId, RowExclusiveLock);
+
+ indexTuple = SearchSysCacheCopy1(INDEXRELID,
+ ObjectIdGetDatum(indexId));
+ if (!HeapTupleIsValid(indexTuple))
+ elog(ERROR, "cache lookup failed for index %u", indexId);
+ indexForm = (Form_pg_index) GETSTRUCT(indexTuple);
+
+ index_bad = (!indexForm->indisvalid ||
+ !indexForm->indisready ||
+ !indexForm->indislive);
+ if (index_bad ||
+ (indexForm->indcheckxmin && !indexInfo->ii_BrokenHotChain) ||
+ early_pruning_enabled)
+ {
+ if (!indexInfo->ii_BrokenHotChain && !early_pruning_enabled)
+ indexForm->indcheckxmin = false;
+ else if (index_bad || early_pruning_enabled)
+ indexForm->indcheckxmin = true;
+ indexForm->indisvalid = true;
+ indexForm->indisready = true;
+ indexForm->indislive = true;
+ CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
+
+ /*
+ * Invalidate the relcache for the table, so that after we commit
+ * all sessions will refresh the table's index list. This ensures
+ * that if anyone misses seeing the pg_index row during this
+ * update, they'll refresh their list before attempting any update
+ * on the table.
+ */
+ CacheInvalidateRelcache(heapRelation);
+ }
+
+ table_close(pg_index, RowExclusiveLock);
+ }
+
+ /* Log what we did */
+ if (options & REINDEXOPT_VERBOSE)
+ ereport(INFO,
+ (errmsg("index \"%s\" was reindexed",
+ get_rel_name(indexId)),
+ errdetail_internal("%s",
+ pg_rusage_show(&ru0))));
+
+ if (progress)
+ pgstat_progress_end_command();
+
+ /* Close rels, but keep locks */
+ index_close(iRel, NoLock);
+ table_close(heapRelation, NoLock);
+}
+
+/*
+ * reindex_relation - This routine is used to recreate all indexes
+ * of a relation (and optionally its toast relation too, if any).
+ *
+ * "flags" is a bitmask that can include any combination of these bits:
+ *
+ * REINDEX_REL_PROCESS_TOAST: if true, process the toast table too (if any).
+ *
+ * REINDEX_REL_SUPPRESS_INDEX_USE: if true, the relation was just completely
+ * rebuilt by an operation such as VACUUM FULL or CLUSTER, and therefore its
+ * indexes are inconsistent with it. This makes things tricky if the relation
+ * is a system catalog that we might consult during the reindexing. To deal
+ * with that case, we mark all of the indexes as pending rebuild so that they
+ * won't be trusted until rebuilt. The caller is required to call us *without*
+ * having made the rebuilt table visible by doing CommandCounterIncrement;
+ * we'll do CCI after having collected the index list. (This way we can still
+ * use catalog indexes while collecting the list.)
+ *
+ * REINDEX_REL_CHECK_CONSTRAINTS: if true, recheck unique and exclusion
+ * constraint conditions, else don't. To avoid deadlocks, VACUUM FULL or
+ * CLUSTER on a system catalog must omit this flag. REINDEX should be used to
+ * rebuild an index if constraint inconsistency is suspected. For optimal
+ * performance, other callers should include the flag only after transforming
+ * the data in a manner that risks a change in constraint validity.
+ *
+ * REINDEX_REL_FORCE_INDEXES_UNLOGGED: if true, set the persistence of the
+ * rebuilt indexes to unlogged.
+ *
+ * REINDEX_REL_FORCE_INDEXES_PERMANENT: if true, set the persistence of the
+ * rebuilt indexes to permanent.
+ *
+ * Returns true if any indexes were rebuilt (including toast table's index
+ * when relevant). Note that a CommandCounterIncrement will occur after each
+ * index rebuild.
+ */
+bool
+reindex_relation(Oid relid, int flags, int options)
+{
+ Relation rel;
+ Oid toast_relid;
+ List *indexIds;
+ char persistence;
+ bool result;
+ ListCell *indexId;
+ int i;
+
+ /*
+ * Open and lock the relation. ShareLock is sufficient since we only need
+ * to prevent schema and data changes in it. The lock level used here
+ * should match ReindexTable().
+ */
+ rel = table_open(relid, ShareLock);
+
+ /*
+ * This may be useful when implemented someday; but that day is not today.
+ * For now, avoid erroring out when called in a multi-table context
+ * (REINDEX SCHEMA) and happen to come across a partitioned table. The
+ * partitions may be reindexed on their own anyway.
+ */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ ereport(WARNING,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("REINDEX of partitioned tables is not yet implemented, skipping \"%s\"",
+ RelationGetRelationName(rel))));
+ table_close(rel, ShareLock);
+ return false;
+ }
+
+ toast_relid = rel->rd_rel->reltoastrelid;
+
+ /*
+ * Get the list of index OIDs for this relation. (We trust to the
+ * relcache to get this with a sequential scan if ignoring system
+ * indexes.)
+ */
+ indexIds = RelationGetIndexList(rel);
+
+ if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
+ {
+ /* Suppress use of all the indexes until they are rebuilt */
+ SetReindexPending(indexIds);
+
+ /*
+ * Make the new heap contents visible --- now things might be
+ * inconsistent!
+ */
+ CommandCounterIncrement();
+ }
+
+ /*
+ * Compute persistence of indexes: same as that of owning rel, unless
+ * caller specified otherwise.
+ */
+ if (flags & REINDEX_REL_FORCE_INDEXES_UNLOGGED)
+ persistence = RELPERSISTENCE_UNLOGGED;
+ else if (flags & REINDEX_REL_FORCE_INDEXES_PERMANENT)
+ persistence = RELPERSISTENCE_PERMANENT;
+ else
+ persistence = rel->rd_rel->relpersistence;
+
+ /* Reindex all the indexes. */
+ i = 1;
+ foreach(indexId, indexIds)
+ {
+ Oid indexOid = lfirst_oid(indexId);
+ Oid indexNamespaceId = get_rel_namespace(indexOid);
+
+ /*
+ * Skip any invalid indexes on a TOAST table. These can only be
+ * duplicate leftovers from a failed REINDEX CONCURRENTLY, and if
+ * rebuilt it would not be possible to drop them anymore.
+ */
+ if (IsToastNamespace(indexNamespaceId) &&
+ !get_index_isvalid(indexOid))
+ {
+ ereport(WARNING,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot reindex invalid index \"%s.%s\" on TOAST table, skipping",
+ get_namespace_name(indexNamespaceId),
+ get_rel_name(indexOid))));
+ continue;
+ }
+
+ reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
+ persistence, options);
+
+ CommandCounterIncrement();
+
+ /* Index should no longer be in the pending list */
+ Assert(!ReindexIsProcessingIndex(indexOid));
+
+ /* Set index rebuild count */
+ pgstat_progress_update_param(PROGRESS_CLUSTER_INDEX_REBUILD_COUNT,
+ i);
+ i++;
+ }
+
+ /*
+ * Close rel, but continue to hold the lock.
+ */
+ table_close(rel, NoLock);
+
+ result = (indexIds != NIL);
+
+ /*
+ * If the relation has a secondary toast rel, reindex that too while we
+ * still hold the lock on the master table.
+ */
+ if ((flags & REINDEX_REL_PROCESS_TOAST) && OidIsValid(toast_relid))
+ result |= reindex_relation(toast_relid, flags, options);
+
+ return result;
+}
+
+
+/* ----------------------------------------------------------------
+ * System index reindexing support
+ *
+ * When we are busy reindexing a system index, this code provides support
+ * for preventing catalog lookups from using that index. We also make use
+ * of this to catch attempted uses of user indexes during reindexing of
+ * those indexes. This information is propagated to parallel workers;
+ * attempting to change it during a parallel operation is not permitted.
+ * ----------------------------------------------------------------
+ */
+
+static Oid currentlyReindexedHeap = InvalidOid;
+static Oid currentlyReindexedIndex = InvalidOid;
+static List *pendingReindexedIndexes = NIL;
+static int reindexingNestLevel = 0;
+
+/*
+ * ReindexIsProcessingHeap
+ * True if heap specified by OID is currently being reindexed.
+ */
+bool
+ReindexIsProcessingHeap(Oid heapOid)
+{
+ return heapOid == currentlyReindexedHeap;
+}
+
+/*
+ * ReindexIsCurrentlyProcessingIndex
+ * True if index specified by OID is currently being reindexed.
+ */
+static bool
+ReindexIsCurrentlyProcessingIndex(Oid indexOid)
+{
+ return indexOid == currentlyReindexedIndex;
+}
+
+/*
+ * ReindexIsProcessingIndex
+ * True if index specified by OID is currently being reindexed,
+ * or should be treated as invalid because it is awaiting reindex.
+ */
+bool
+ReindexIsProcessingIndex(Oid indexOid)
+{
+ return indexOid == currentlyReindexedIndex ||
+ list_member_oid(pendingReindexedIndexes, indexOid);
+}
+
+/*
+ * SetReindexProcessing
+ * Set flag that specified heap/index are being reindexed.
+ */
+static void
+SetReindexProcessing(Oid heapOid, Oid indexOid)
+{
+ Assert(OidIsValid(heapOid) && OidIsValid(indexOid));
+ /* Reindexing is not re-entrant. */
+ if (OidIsValid(currentlyReindexedHeap))
+ elog(ERROR, "cannot reindex while reindexing");
+ currentlyReindexedHeap = heapOid;
+ currentlyReindexedIndex = indexOid;
+ /* Index is no longer "pending" reindex. */
+ RemoveReindexPending(indexOid);
+ /* This may have been set already, but in case it isn't, do so now. */
+ reindexingNestLevel = GetCurrentTransactionNestLevel();
+}
+
+/*
+ * ResetReindexProcessing
+ * Unset reindexing status.
+ */
+static void
+ResetReindexProcessing(void)
+{
+ currentlyReindexedHeap = InvalidOid;
+ currentlyReindexedIndex = InvalidOid;
+ /* reindexingNestLevel remains set till end of (sub)transaction */
+}
+
+/*
+ * SetReindexPending
+ * Mark the given indexes as pending reindex.
+ *
+ * NB: we assume that the current memory context stays valid throughout.
+ */
+static void
+SetReindexPending(List *indexes)
+{
+ /* Reindexing is not re-entrant. */
+ if (pendingReindexedIndexes)
+ elog(ERROR, "cannot reindex while reindexing");
+ if (IsInParallelMode())
+ elog(ERROR, "cannot modify reindex state during a parallel operation");
+ pendingReindexedIndexes = list_copy(indexes);
+ reindexingNestLevel = GetCurrentTransactionNestLevel();
+}
+
+/*
+ * RemoveReindexPending
+ * Remove the given index from the pending list.
+ */
+static void
+RemoveReindexPending(Oid indexOid)
+{
+ if (IsInParallelMode())
+ elog(ERROR, "cannot modify reindex state during a parallel operation");
+ pendingReindexedIndexes = list_delete_oid(pendingReindexedIndexes,
+ indexOid);
+}
+
+/*
+ * ResetReindexState
+ * Clear all reindexing state during (sub)transaction abort.
+ */
+void
+ResetReindexState(int nestLevel)
+{
+ /*
+ * Because reindexing is not re-entrant, we don't need to cope with nested
+ * reindexing states. We just need to avoid messing up the outer-level
+ * state in case a subtransaction fails within a REINDEX. So checking the
+ * current nest level against that of the reindex operation is sufficient.
+ */
+ if (reindexingNestLevel >= nestLevel)
+ {
+ currentlyReindexedHeap = InvalidOid;
+ currentlyReindexedIndex = InvalidOid;
+
+ /*
+ * We needn't try to release the contents of pendingReindexedIndexes;
+ * that list should be in a transaction-lifespan context, so it will
+ * go away automatically.
+ */
+ pendingReindexedIndexes = NIL;
+
+ reindexingNestLevel = 0;
+ }
+}
+
+/*
+ * EstimateReindexStateSpace
+ * Estimate space needed to pass reindex state to parallel workers.
+ */
+Size
+EstimateReindexStateSpace(void)
+{
+ return offsetof(SerializedReindexState, pendingReindexedIndexes)
+ + mul_size(sizeof(Oid), list_length(pendingReindexedIndexes));
+}
+
+/*
+ * SerializeReindexState
+ * Serialize reindex state for parallel workers.
+ */
+void
+SerializeReindexState(Size maxsize, char *start_address)
+{
+ SerializedReindexState *sistate = (SerializedReindexState *) start_address;
+ int c = 0;
+ ListCell *lc;
+
+ sistate->currentlyReindexedHeap = currentlyReindexedHeap;
+ sistate->currentlyReindexedIndex = currentlyReindexedIndex;
+ sistate->numPendingReindexedIndexes = list_length(pendingReindexedIndexes);
+ foreach(lc, pendingReindexedIndexes)
+ sistate->pendingReindexedIndexes[c++] = lfirst_oid(lc);
+}
+
+/*
+ * RestoreReindexState
+ * Restore reindex state in a parallel worker.
+ */
+void
+RestoreReindexState(void *reindexstate)
+{
+ SerializedReindexState *sistate = (SerializedReindexState *) reindexstate;
+ int c = 0;
+ MemoryContext oldcontext;
+
+ currentlyReindexedHeap = sistate->currentlyReindexedHeap;
+ currentlyReindexedIndex = sistate->currentlyReindexedIndex;
+
+ Assert(pendingReindexedIndexes == NIL);
+ oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+ for (c = 0; c < sistate->numPendingReindexedIndexes; ++c)
+ pendingReindexedIndexes =
+ lappend_oid(pendingReindexedIndexes,
+ sistate->pendingReindexedIndexes[c]);
+ MemoryContextSwitchTo(oldcontext);
+
+ /* Note the worker has its own transaction nesting level */
+ reindexingNestLevel = GetCurrentTransactionNestLevel();
+}
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
new file mode 100644
index 0000000..fe277f3
--- /dev/null
+++ b/src/backend/catalog/indexing.c
@@ -0,0 +1,317 @@
+/*-------------------------------------------------------------------------
+ *
+ * indexing.c
+ * This file contains routines to support indexes defined on system
+ * catalogs.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/indexing.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "catalog/index.h"
+#include "catalog/indexing.h"
+#include "executor/executor.h"
+#include "utils/rel.h"
+
+
+/*
+ * CatalogOpenIndexes - open the indexes on a system catalog.
+ *
+ * When inserting or updating tuples in a system catalog, call this
+ * to prepare to update the indexes for the catalog.
+ *
+ * In the current implementation, we share code for opening/closing the
+ * indexes with execUtils.c. But we do not use ExecInsertIndexTuples,
+ * because we don't want to create an EState. This implies that we
+ * do not support partial or expressional indexes on system catalogs,
+ * nor can we support generalized exclusion constraints.
+ * This could be fixed with localized changes here if we wanted to pay
+ * the extra overhead of building an EState.
+ */
+CatalogIndexState
+CatalogOpenIndexes(Relation heapRel)
+{
+ ResultRelInfo *resultRelInfo;
+
+ resultRelInfo = makeNode(ResultRelInfo);
+ resultRelInfo->ri_RangeTableIndex = 0; /* dummy */
+ resultRelInfo->ri_RelationDesc = heapRel;
+ resultRelInfo->ri_TrigDesc = NULL; /* we don't fire triggers */
+
+ ExecOpenIndices(resultRelInfo, false);
+
+ return resultRelInfo;
+}
+
+/*
+ * CatalogCloseIndexes - clean up resources allocated by CatalogOpenIndexes
+ */
+void
+CatalogCloseIndexes(CatalogIndexState indstate)
+{
+ ExecCloseIndices(indstate);
+ pfree(indstate);
+}
+
+/*
+ * CatalogIndexInsert - insert index entries for one catalog tuple
+ *
+ * This should be called for each inserted or updated catalog tuple.
+ *
+ * This is effectively a cut-down version of ExecInsertIndexTuples.
+ */
+static void
+CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
+{
+ int i;
+ int numIndexes;
+ RelationPtr relationDescs;
+ Relation heapRelation;
+ TupleTableSlot *slot;
+ IndexInfo **indexInfoArray;
+ Datum values[INDEX_MAX_KEYS];
+ bool isnull[INDEX_MAX_KEYS];
+
+ /*
+ * HOT update does not require index inserts. But with asserts enabled we
+ * want to check that it'd be legal to currently insert into the
+ * table/index.
+ */
+#ifndef USE_ASSERT_CHECKING
+ if (HeapTupleIsHeapOnly(heapTuple))
+ return;
+#endif
+
+ /*
+ * Get information from the state structure. Fall out if nothing to do.
+ */
+ numIndexes = indstate->ri_NumIndices;
+ if (numIndexes == 0)
+ return;
+ relationDescs = indstate->ri_IndexRelationDescs;
+ indexInfoArray = indstate->ri_IndexRelationInfo;
+ heapRelation = indstate->ri_RelationDesc;
+
+ /* Need a slot to hold the tuple being examined */
+ slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
+ &TTSOpsHeapTuple);
+ ExecStoreHeapTuple(heapTuple, slot, false);
+
+ /*
+ * for each index, form and insert the index tuple
+ */
+ for (i = 0; i < numIndexes; i++)
+ {
+ IndexInfo *indexInfo;
+ Relation index;
+
+ indexInfo = indexInfoArray[i];
+ index = relationDescs[i];
+
+ /* If the index is marked as read-only, ignore it */
+ if (!indexInfo->ii_ReadyForInserts)
+ continue;
+
+ /*
+ * Expressional and partial indexes on system catalogs are not
+ * supported, nor exclusion constraints, nor deferred uniqueness
+ */
+ Assert(indexInfo->ii_Expressions == NIL);
+ Assert(indexInfo->ii_Predicate == NIL);
+ Assert(indexInfo->ii_ExclusionOps == NULL);
+ Assert(index->rd_index->indimmediate);
+ Assert(indexInfo->ii_NumIndexKeyAttrs != 0);
+
+ /* see earlier check above */
+#ifdef USE_ASSERT_CHECKING
+ if (HeapTupleIsHeapOnly(heapTuple))
+ {
+ Assert(!ReindexIsProcessingIndex(RelationGetRelid(index)));
+ continue;
+ }
+#endif /* USE_ASSERT_CHECKING */
+
+ /*
+ * FormIndexDatum fills in its values and isnull parameters with the
+ * appropriate values for the column(s) of the index.
+ */
+ FormIndexDatum(indexInfo,
+ slot,
+ NULL, /* no expression eval to do */
+ values,
+ isnull);
+
+ /*
+ * The index AM does the rest.
+ */
+ index_insert(index, /* index relation */
+ values, /* array of index Datums */
+ isnull, /* is-null flags */
+ &(heapTuple->t_self), /* tid of heap tuple */
+ heapRelation,
+ index->rd_index->indisunique ?
+ UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
+ indexInfo);
+ }
+
+ ExecDropSingleTupleTableSlot(slot);
+}
+
+/*
+ * Subroutine to verify that catalog constraints are honored.
+ *
+ * Tuples inserted via CatalogTupleInsert/CatalogTupleUpdate are generally
+ * "hand made", so that it's possible that they fail to satisfy constraints
+ * that would be checked if they were being inserted by the executor. That's
+ * a coding error, so we only bother to check for it in assert-enabled builds.
+ */
+#ifdef USE_ASSERT_CHECKING
+
+static void
+CatalogTupleCheckConstraints(Relation heapRel, HeapTuple tup)
+{
+ /*
+ * Currently, the only constraints implemented for system catalogs are
+ * attnotnull constraints.
+ */
+ if (HeapTupleHasNulls(tup))
+ {
+ TupleDesc tupdesc = RelationGetDescr(heapRel);
+ bits8 *bp = tup->t_data->t_bits;
+
+ for (int attnum = 0; attnum < tupdesc->natts; attnum++)
+ {
+ Form_pg_attribute thisatt = TupleDescAttr(tupdesc, attnum);
+
+ Assert(!(thisatt->attnotnull && att_isnull(attnum, bp)));
+ }
+ }
+}
+
+#else /* !USE_ASSERT_CHECKING */
+
+#define CatalogTupleCheckConstraints(heapRel, tup) ((void) 0)
+
+#endif /* USE_ASSERT_CHECKING */
+
+/*
+ * CatalogTupleInsert - do heap and indexing work for a new catalog tuple
+ *
+ * Insert the tuple data in "tup" into the specified catalog relation.
+ * The Oid of the inserted tuple is returned.
+ *
+ * This is a convenience routine for the common case of inserting a single
+ * tuple in a system catalog; it inserts a new heap tuple, keeping indexes
+ * current. Avoid using it for multiple tuples, since opening the indexes
+ * and building the index info structures is moderately expensive.
+ * (Use CatalogTupleInsertWithInfo in such cases.)
+ */
+void
+CatalogTupleInsert(Relation heapRel, HeapTuple tup)
+{
+ CatalogIndexState indstate;
+
+ CatalogTupleCheckConstraints(heapRel, tup);
+
+ indstate = CatalogOpenIndexes(heapRel);
+
+ simple_heap_insert(heapRel, tup);
+
+ CatalogIndexInsert(indstate, tup);
+ CatalogCloseIndexes(indstate);
+}
+
+/*
+ * CatalogTupleInsertWithInfo - as above, but with caller-supplied index info
+ *
+ * This should be used when it's important to amortize CatalogOpenIndexes/
+ * CatalogCloseIndexes work across multiple insertions. At some point we
+ * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
+ * so that callers needn't trouble over this ... but we don't do so today.
+ */
+void
+CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
+ CatalogIndexState indstate)
+{
+ CatalogTupleCheckConstraints(heapRel, tup);
+
+ simple_heap_insert(heapRel, tup);
+
+ CatalogIndexInsert(indstate, tup);
+}
+
+/*
+ * CatalogTupleUpdate - do heap and indexing work for updating a catalog tuple
+ *
+ * Update the tuple identified by "otid", replacing it with the data in "tup".
+ *
+ * This is a convenience routine for the common case of updating a single
+ * tuple in a system catalog; it updates one heap tuple, keeping indexes
+ * current. Avoid using it for multiple tuples, since opening the indexes
+ * and building the index info structures is moderately expensive.
+ * (Use CatalogTupleUpdateWithInfo in such cases.)
+ */
+void
+CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
+{
+ CatalogIndexState indstate;
+
+ CatalogTupleCheckConstraints(heapRel, tup);
+
+ indstate = CatalogOpenIndexes(heapRel);
+
+ simple_heap_update(heapRel, otid, tup);
+
+ CatalogIndexInsert(indstate, tup);
+ CatalogCloseIndexes(indstate);
+}
+
+/*
+ * CatalogTupleUpdateWithInfo - as above, but with caller-supplied index info
+ *
+ * This should be used when it's important to amortize CatalogOpenIndexes/
+ * CatalogCloseIndexes work across multiple updates. At some point we
+ * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
+ * so that callers needn't trouble over this ... but we don't do so today.
+ */
+void
+CatalogTupleUpdateWithInfo(Relation heapRel, ItemPointer otid, HeapTuple tup,
+ CatalogIndexState indstate)
+{
+ CatalogTupleCheckConstraints(heapRel, tup);
+
+ simple_heap_update(heapRel, otid, tup);
+
+ CatalogIndexInsert(indstate, tup);
+}
+
+/*
+ * CatalogTupleDelete - do heap and indexing work for deleting a catalog tuple
+ *
+ * Delete the tuple identified by "tid" in the specified catalog.
+ *
+ * With Postgres heaps, there is no index work to do at deletion time;
+ * cleanup will be done later by VACUUM. However, callers of this function
+ * shouldn't have to know that; we'd like a uniform abstraction for all
+ * catalog tuple changes. Hence, provide this currently-trivial wrapper.
+ *
+ * The abstraction is a bit leaky in that we don't provide an optimized
+ * CatalogTupleDeleteWithInfo version, because there is currently nothing to
+ * optimize. If we ever need that, rather than touching a lot of call sites,
+ * it might be better to do something about caching CatalogIndexState.
+ */
+void
+CatalogTupleDelete(Relation heapRel, ItemPointer tid)
+{
+ simple_heap_delete(heapRel, tid);
+}
diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql
new file mode 100644
index 0000000..3e07fb1
--- /dev/null
+++ b/src/backend/catalog/information_schema.sql
@@ -0,0 +1,2937 @@
+/*
+ * SQL Information Schema
+ * as defined in ISO/IEC 9075-11:2016
+ *
+ * Copyright (c) 2003-2020, PostgreSQL Global Development Group
+ *
+ * src/backend/catalog/information_schema.sql
+ *
+ * Note: this file is read in single-user -j mode, which means that the
+ * command terminator is semicolon-newline-newline; whenever the backend
+ * sees that, it stops and executes what it's got. If you write a lot of
+ * statements without empty lines between, they'll all get quoted to you
+ * in any error message about one of them, so don't do that. Also, you
+ * cannot write a semicolon immediately followed by an empty line in a
+ * string literal (including a function body!) or a multiline comment.
+ */
+
+/*
+ * Note: Generally, the definitions in this file should be ordered
+ * according to the clause numbers in the SQL standard, which is also the
+ * alphabetical order. In some cases it is convenient or necessary to
+ * define one information schema view by using another one; in that case,
+ * put the referencing view at the very end and leave a note where it
+ * should have been put.
+ */
+
+
+/*
+ * 5.1
+ * INFORMATION_SCHEMA schema
+ */
+
+CREATE SCHEMA information_schema;
+GRANT USAGE ON SCHEMA information_schema TO PUBLIC;
+SET search_path TO information_schema;
+
+
+/*
+ * A few supporting functions first ...
+ */
+
+/* Expand any 1-D array into a set with integers 1..N */
+CREATE FUNCTION _pg_expandarray(IN anyarray, OUT x anyelement, OUT n int)
+ RETURNS SETOF RECORD
+ LANGUAGE sql STRICT IMMUTABLE PARALLEL SAFE
+ AS 'select $1[s], s - pg_catalog.array_lower($1,1) + 1
+ from pg_catalog.generate_series(pg_catalog.array_lower($1,1),
+ pg_catalog.array_upper($1,1),
+ 1) as g(s)';
+
+/* Given an index's OID and an underlying-table column number, return the
+ * column's position in the index (NULL if not there) */
+CREATE FUNCTION _pg_index_position(oid, smallint) RETURNS int
+ LANGUAGE sql STRICT STABLE
+ AS $$
+SELECT (ss.a).n FROM
+ (SELECT information_schema._pg_expandarray(indkey) AS a
+ FROM pg_catalog.pg_index WHERE indexrelid = $1) ss
+ WHERE (ss.a).x = $2;
+$$;
+
+CREATE FUNCTION _pg_truetypid(pg_attribute, pg_type) RETURNS oid
+ LANGUAGE sql
+ IMMUTABLE
+ PARALLEL SAFE
+ RETURNS NULL ON NULL INPUT
+ AS
+$$SELECT CASE WHEN $2.typtype = 'd' THEN $2.typbasetype ELSE $1.atttypid END$$;
+
+CREATE FUNCTION _pg_truetypmod(pg_attribute, pg_type) RETURNS int4
+ LANGUAGE sql
+ IMMUTABLE
+ PARALLEL SAFE
+ RETURNS NULL ON NULL INPUT
+ AS
+$$SELECT CASE WHEN $2.typtype = 'd' THEN $2.typtypmod ELSE $1.atttypmod END$$;
+
+-- these functions encapsulate knowledge about the encoding of typmod:
+
+CREATE FUNCTION _pg_char_max_length(typid oid, typmod int4) RETURNS integer
+ LANGUAGE sql
+ IMMUTABLE
+ PARALLEL SAFE
+ RETURNS NULL ON NULL INPUT
+ AS
+$$SELECT
+ CASE WHEN $2 = -1 /* default typmod */
+ THEN null
+ WHEN $1 IN (1042, 1043) /* char, varchar */
+ THEN $2 - 4
+ WHEN $1 IN (1560, 1562) /* bit, varbit */
+ THEN $2
+ ELSE null
+ END$$;
+
+CREATE FUNCTION _pg_char_octet_length(typid oid, typmod int4) RETURNS integer
+ LANGUAGE sql
+ IMMUTABLE
+ PARALLEL SAFE
+ RETURNS NULL ON NULL INPUT
+ AS
+$$SELECT
+ CASE WHEN $1 IN (25, 1042, 1043) /* text, char, varchar */
+ THEN CASE WHEN $2 = -1 /* default typmod */
+ THEN CAST(2^30 AS integer)
+ ELSE information_schema._pg_char_max_length($1, $2) *
+ pg_catalog.pg_encoding_max_length((SELECT encoding FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database()))
+ END
+ ELSE null
+ END$$;
+
+CREATE FUNCTION _pg_numeric_precision(typid oid, typmod int4) RETURNS integer
+ LANGUAGE sql
+ IMMUTABLE
+ PARALLEL SAFE
+ RETURNS NULL ON NULL INPUT
+ AS
+$$SELECT
+ CASE $1
+ WHEN 21 /*int2*/ THEN 16
+ WHEN 23 /*int4*/ THEN 32
+ WHEN 20 /*int8*/ THEN 64
+ WHEN 1700 /*numeric*/ THEN
+ CASE WHEN $2 = -1
+ THEN null
+ ELSE (($2 - 4) >> 16) & 65535
+ END
+ WHEN 700 /*float4*/ THEN 24 /*FLT_MANT_DIG*/
+ WHEN 701 /*float8*/ THEN 53 /*DBL_MANT_DIG*/
+ ELSE null
+ END$$;
+
+CREATE FUNCTION _pg_numeric_precision_radix(typid oid, typmod int4) RETURNS integer
+ LANGUAGE sql
+ IMMUTABLE
+ PARALLEL SAFE
+ RETURNS NULL ON NULL INPUT
+ AS
+$$SELECT
+ CASE WHEN $1 IN (21, 23, 20, 700, 701) THEN 2
+ WHEN $1 IN (1700) THEN 10
+ ELSE null
+ END$$;
+
+CREATE FUNCTION _pg_numeric_scale(typid oid, typmod int4) RETURNS integer
+ LANGUAGE sql
+ IMMUTABLE
+ PARALLEL SAFE
+ RETURNS NULL ON NULL INPUT
+ AS
+$$SELECT
+ CASE WHEN $1 IN (21, 23, 20) THEN 0
+ WHEN $1 IN (1700) THEN
+ CASE WHEN $2 = -1
+ THEN null
+ ELSE ($2 - 4) & 65535
+ END
+ ELSE null
+ END$$;
+
+CREATE FUNCTION _pg_datetime_precision(typid oid, typmod int4) RETURNS integer
+ LANGUAGE sql
+ IMMUTABLE
+ PARALLEL SAFE
+ RETURNS NULL ON NULL INPUT
+ AS
+$$SELECT
+ CASE WHEN $1 IN (1082) /* date */
+ THEN 0
+ WHEN $1 IN (1083, 1114, 1184, 1266) /* time, timestamp, same + tz */
+ THEN CASE WHEN $2 < 0 THEN 6 ELSE $2 END
+ WHEN $1 IN (1186) /* interval */
+ THEN CASE WHEN $2 < 0 OR $2 & 65535 = 65535 THEN 6 ELSE $2 & 65535 END
+ ELSE null
+ END$$;
+
+CREATE FUNCTION _pg_interval_type(typid oid, mod int4) RETURNS text
+ LANGUAGE sql
+ IMMUTABLE
+ PARALLEL SAFE
+ RETURNS NULL ON NULL INPUT
+ AS
+$$SELECT
+ CASE WHEN $1 IN (1186) /* interval */
+ THEN pg_catalog.upper(substring(pg_catalog.format_type($1, $2) from 'interval[()0-9]* #"%#"' for '#'))
+ ELSE null
+ END$$;
+
+
+-- 5.2 INFORMATION_SCHEMA_CATALOG_NAME view appears later.
+
+
+/*
+ * 5.3
+ * CARDINAL_NUMBER domain
+ */
+
+CREATE DOMAIN cardinal_number AS integer
+ CONSTRAINT cardinal_number_domain_check CHECK (value >= 0);
+
+
+/*
+ * 5.4
+ * CHARACTER_DATA domain
+ */
+
+CREATE DOMAIN character_data AS character varying COLLATE "C";
+
+
+/*
+ * 5.5
+ * SQL_IDENTIFIER domain
+ */
+
+CREATE DOMAIN sql_identifier AS name;
+
+
+/*
+ * 5.2
+ * INFORMATION_SCHEMA_CATALOG_NAME view
+ */
+
+CREATE VIEW information_schema_catalog_name AS
+ SELECT CAST(current_database() AS sql_identifier) AS catalog_name;
+
+GRANT SELECT ON information_schema_catalog_name TO PUBLIC;
+
+
+/*
+ * 5.6
+ * TIME_STAMP domain
+ */
+
+CREATE DOMAIN time_stamp AS timestamp(2) with time zone
+ DEFAULT current_timestamp(2);
+
+/*
+ * 5.7
+ * YES_OR_NO domain
+ */
+
+CREATE DOMAIN yes_or_no AS character varying(3) COLLATE "C"
+ CONSTRAINT yes_or_no_check CHECK (value IN ('YES', 'NO'));
+
+
+-- 5.8 ADMINISTRABLE_ROLE_AUTHORIZATIONS view appears later.
+
+
+/*
+ * 5.9
+ * APPLICABLE_ROLES view
+ */
+
+CREATE VIEW applicable_roles AS
+ SELECT CAST(a.rolname AS sql_identifier) AS grantee,
+ CAST(b.rolname AS sql_identifier) AS role_name,
+ CAST(CASE WHEN m.admin_option THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_grantable
+ FROM pg_auth_members m
+ JOIN pg_authid a ON (m.member = a.oid)
+ JOIN pg_authid b ON (m.roleid = b.oid)
+ WHERE pg_has_role(a.oid, 'USAGE');
+
+GRANT SELECT ON applicable_roles TO PUBLIC;
+
+
+/*
+ * 5.8
+ * ADMINISTRABLE_ROLE_AUTHORIZATIONS view
+ */
+
+CREATE VIEW administrable_role_authorizations AS
+ SELECT *
+ FROM applicable_roles
+ WHERE is_grantable = 'YES';
+
+GRANT SELECT ON administrable_role_authorizations TO PUBLIC;
+
+
+/*
+ * 5.10
+ * ASSERTIONS view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.11
+ * ATTRIBUTES view
+ */
+
+CREATE VIEW attributes AS
+ SELECT CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(nc.nspname AS sql_identifier) AS udt_schema,
+ CAST(c.relname AS sql_identifier) AS udt_name,
+ CAST(a.attname AS sql_identifier) AS attribute_name,
+ CAST(a.attnum AS cardinal_number) AS ordinal_position,
+ CAST(pg_get_expr(ad.adbin, ad.adrelid) AS character_data) AS attribute_default,
+ CAST(CASE WHEN a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END
+ AS yes_or_no)
+ AS is_nullable, -- This column was apparently removed between SQL:2003 and SQL:2008.
+
+ CAST(
+ CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY'
+ WHEN nt.nspname = 'pg_catalog' THEN format_type(a.atttypid, null)
+ ELSE 'USER-DEFINED' END
+ AS character_data)
+ AS data_type,
+
+ CAST(
+ _pg_char_max_length(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS character_maximum_length,
+
+ CAST(
+ _pg_char_octet_length(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS character_octet_length,
+
+ CAST(null AS sql_identifier) AS character_set_catalog,
+ CAST(null AS sql_identifier) AS character_set_schema,
+ CAST(null AS sql_identifier) AS character_set_name,
+
+ CAST(CASE WHEN nco.nspname IS NOT NULL THEN current_database() END AS sql_identifier) AS collation_catalog,
+ CAST(nco.nspname AS sql_identifier) AS collation_schema,
+ CAST(co.collname AS sql_identifier) AS collation_name,
+
+ CAST(
+ _pg_numeric_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS numeric_precision,
+
+ CAST(
+ _pg_numeric_precision_radix(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS numeric_precision_radix,
+
+ CAST(
+ _pg_numeric_scale(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS numeric_scale,
+
+ CAST(
+ _pg_datetime_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS datetime_precision,
+
+ CAST(
+ _pg_interval_type(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS character_data)
+ AS interval_type,
+ CAST(null AS cardinal_number) AS interval_precision,
+
+ CAST(current_database() AS sql_identifier) AS attribute_udt_catalog,
+ CAST(nt.nspname AS sql_identifier) AS attribute_udt_schema,
+ CAST(t.typname AS sql_identifier) AS attribute_udt_name,
+
+ CAST(null AS sql_identifier) AS scope_catalog,
+ CAST(null AS sql_identifier) AS scope_schema,
+ CAST(null AS sql_identifier) AS scope_name,
+
+ CAST(null AS cardinal_number) AS maximum_cardinality,
+ CAST(a.attnum AS sql_identifier) AS dtd_identifier,
+ CAST('NO' AS yes_or_no) AS is_derived_reference_attribute
+
+ FROM (pg_attribute a LEFT JOIN pg_attrdef ad ON attrelid = adrelid AND attnum = adnum)
+ JOIN (pg_class c JOIN pg_namespace nc ON (c.relnamespace = nc.oid)) ON a.attrelid = c.oid
+ JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON a.atttypid = t.oid
+ LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid))
+ ON a.attcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default')
+
+ WHERE a.attnum > 0 AND NOT a.attisdropped
+ AND c.relkind IN ('c')
+ AND (pg_has_role(c.relowner, 'USAGE')
+ OR has_type_privilege(c.reltype, 'USAGE'));
+
+GRANT SELECT ON attributes TO PUBLIC;
+
+
+/*
+ * 5.12
+ * CHARACTER_SETS view
+ */
+
+CREATE VIEW character_sets AS
+ SELECT CAST(null AS sql_identifier) AS character_set_catalog,
+ CAST(null AS sql_identifier) AS character_set_schema,
+ CAST(getdatabaseencoding() AS sql_identifier) AS character_set_name,
+ CAST(CASE WHEN getdatabaseencoding() = 'UTF8' THEN 'UCS' ELSE getdatabaseencoding() END AS sql_identifier) AS character_repertoire,
+ CAST(getdatabaseencoding() AS sql_identifier) AS form_of_use,
+ CAST(current_database() AS sql_identifier) AS default_collate_catalog,
+ CAST(nc.nspname AS sql_identifier) AS default_collate_schema,
+ CAST(c.collname AS sql_identifier) AS default_collate_name
+ FROM pg_database d
+ LEFT JOIN (pg_collation c JOIN pg_namespace nc ON (c.collnamespace = nc.oid))
+ ON (datcollate = collcollate AND datctype = collctype)
+ WHERE d.datname = current_database()
+ ORDER BY char_length(c.collname) DESC, c.collname ASC -- prefer full/canonical name
+ LIMIT 1;
+
+GRANT SELECT ON character_sets TO PUBLIC;
+
+
+/*
+ * 5.13
+ * CHECK_CONSTRAINT_ROUTINE_USAGE view
+ */
+
+CREATE VIEW check_constraint_routine_usage AS
+ SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(nc.nspname AS sql_identifier) AS constraint_schema,
+ CAST(c.conname AS sql_identifier) AS constraint_name,
+ CAST(current_database() AS sql_identifier) AS specific_catalog,
+ CAST(np.nspname AS sql_identifier) AS specific_schema,
+ CAST(nameconcatoid(p.proname, p.oid) AS sql_identifier) AS specific_name
+ FROM pg_namespace nc, pg_constraint c, pg_depend d, pg_proc p, pg_namespace np
+ WHERE nc.oid = c.connamespace
+ AND c.contype = 'c'
+ AND c.oid = d.objid
+ AND d.classid = 'pg_catalog.pg_constraint'::regclass
+ AND d.refobjid = p.oid
+ AND d.refclassid = 'pg_catalog.pg_proc'::regclass
+ AND p.pronamespace = np.oid
+ AND pg_has_role(p.proowner, 'USAGE');
+
+GRANT SELECT ON check_constraint_routine_usage TO PUBLIC;
+
+
+/*
+ * 5.14
+ * CHECK_CONSTRAINTS view
+ */
+
+CREATE VIEW check_constraints AS
+ SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(rs.nspname AS sql_identifier) AS constraint_schema,
+ CAST(con.conname AS sql_identifier) AS constraint_name,
+ CAST(substring(pg_get_constraintdef(con.oid) from 7) AS character_data)
+ AS check_clause
+ FROM pg_constraint con
+ LEFT OUTER JOIN pg_namespace rs ON (rs.oid = con.connamespace)
+ LEFT OUTER JOIN pg_class c ON (c.oid = con.conrelid)
+ LEFT OUTER JOIN pg_type t ON (t.oid = con.contypid)
+ WHERE pg_has_role(coalesce(c.relowner, t.typowner), 'USAGE')
+ AND con.contype = 'c'
+
+ UNION
+ -- not-null constraints
+
+ SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(n.nspname AS sql_identifier) AS constraint_schema,
+ CAST(CAST(n.oid AS text) || '_' || CAST(r.oid AS text) || '_' || CAST(a.attnum AS text) || '_not_null' AS sql_identifier) AS constraint_name, -- XXX
+ CAST(a.attname || ' IS NOT NULL' AS character_data)
+ AS check_clause
+ FROM pg_namespace n, pg_class r, pg_attribute a
+ WHERE n.oid = r.relnamespace
+ AND r.oid = a.attrelid
+ AND a.attnum > 0
+ AND NOT a.attisdropped
+ AND a.attnotnull
+ AND r.relkind IN ('r', 'p')
+ AND pg_has_role(r.relowner, 'USAGE');
+
+GRANT SELECT ON check_constraints TO PUBLIC;
+
+
+/*
+ * 5.15
+ * COLLATIONS view
+ */
+
+CREATE VIEW collations AS
+ SELECT CAST(current_database() AS sql_identifier) AS collation_catalog,
+ CAST(nc.nspname AS sql_identifier) AS collation_schema,
+ CAST(c.collname AS sql_identifier) AS collation_name,
+ CAST('NO PAD' AS character_data) AS pad_attribute
+ FROM pg_collation c, pg_namespace nc
+ WHERE c.collnamespace = nc.oid
+ AND collencoding IN (-1, (SELECT encoding FROM pg_database WHERE datname = current_database()));
+
+GRANT SELECT ON collations TO PUBLIC;
+
+
+/*
+ * 5.16
+ * COLLATION_CHARACTER_SET_APPLICABILITY view
+ */
+
+CREATE VIEW collation_character_set_applicability AS
+ SELECT CAST(current_database() AS sql_identifier) AS collation_catalog,
+ CAST(nc.nspname AS sql_identifier) AS collation_schema,
+ CAST(c.collname AS sql_identifier) AS collation_name,
+ CAST(null AS sql_identifier) AS character_set_catalog,
+ CAST(null AS sql_identifier) AS character_set_schema,
+ CAST(getdatabaseencoding() AS sql_identifier) AS character_set_name
+ FROM pg_collation c, pg_namespace nc
+ WHERE c.collnamespace = nc.oid
+ AND collencoding IN (-1, (SELECT encoding FROM pg_database WHERE datname = current_database()));
+
+GRANT SELECT ON collation_character_set_applicability TO PUBLIC;
+
+
+/*
+ * 5.17
+ * COLUMN_COLUMN_USAGE view
+ */
+
+CREATE VIEW column_column_usage AS
+ SELECT CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(n.nspname AS sql_identifier) AS table_schema,
+ CAST(c.relname AS sql_identifier) AS table_name,
+ CAST(ac.attname AS sql_identifier) AS column_name,
+ CAST(ad.attname AS sql_identifier) AS dependent_column
+
+ FROM pg_namespace n, pg_class c, pg_depend d,
+ pg_attribute ac, pg_attribute ad
+
+ WHERE n.oid = c.relnamespace
+ AND c.oid = ac.attrelid
+ AND c.oid = ad.attrelid
+ AND d.classid = 'pg_catalog.pg_class'::regclass
+ AND d.refclassid = 'pg_catalog.pg_class'::regclass
+ AND d.objid = d.refobjid
+ AND c.oid = d.objid
+ AND d.objsubid = ad.attnum
+ AND d.refobjsubid = ac.attnum
+ AND ad.attgenerated <> ''
+ AND pg_has_role(c.relowner, 'USAGE');
+
+GRANT SELECT ON column_column_usage TO PUBLIC;
+
+
+/*
+ * 5.18
+ * COLUMN_DOMAIN_USAGE view
+ */
+
+CREATE VIEW column_domain_usage AS
+ SELECT CAST(current_database() AS sql_identifier) AS domain_catalog,
+ CAST(nt.nspname AS sql_identifier) AS domain_schema,
+ CAST(t.typname AS sql_identifier) AS domain_name,
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nc.nspname AS sql_identifier) AS table_schema,
+ CAST(c.relname AS sql_identifier) AS table_name,
+ CAST(a.attname AS sql_identifier) AS column_name
+
+ FROM pg_type t, pg_namespace nt, pg_class c, pg_namespace nc,
+ pg_attribute a
+
+ WHERE t.typnamespace = nt.oid
+ AND c.relnamespace = nc.oid
+ AND a.attrelid = c.oid
+ AND a.atttypid = t.oid
+ AND t.typtype = 'd'
+ AND c.relkind IN ('r', 'v', 'f', 'p')
+ AND a.attnum > 0
+ AND NOT a.attisdropped
+ AND pg_has_role(t.typowner, 'USAGE');
+
+GRANT SELECT ON column_domain_usage TO PUBLIC;
+
+
+/*
+ * 5.19
+ * COLUMN_PRIVILEGES
+ */
+
+CREATE VIEW column_privileges AS
+ SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
+ CAST(grantee.rolname AS sql_identifier) AS grantee,
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nc.nspname AS sql_identifier) AS table_schema,
+ CAST(x.relname AS sql_identifier) AS table_name,
+ CAST(x.attname AS sql_identifier) AS column_name,
+ CAST(x.prtype AS character_data) AS privilege_type,
+ CAST(
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(x.grantee, x.relowner, 'USAGE')
+ OR x.grantable
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_grantable
+
+ FROM (
+ SELECT pr_c.grantor,
+ pr_c.grantee,
+ attname,
+ relname,
+ relnamespace,
+ pr_c.prtype,
+ pr_c.grantable,
+ pr_c.relowner
+ FROM (SELECT oid, relname, relnamespace, relowner, (aclexplode(coalesce(relacl, acldefault('r', relowner)))).*
+ FROM pg_class
+ WHERE relkind IN ('r', 'v', 'f', 'p')
+ ) pr_c (oid, relname, relnamespace, relowner, grantor, grantee, prtype, grantable),
+ pg_attribute a
+ WHERE a.attrelid = pr_c.oid
+ AND a.attnum > 0
+ AND NOT a.attisdropped
+ UNION
+ SELECT pr_a.grantor,
+ pr_a.grantee,
+ attname,
+ relname,
+ relnamespace,
+ pr_a.prtype,
+ pr_a.grantable,
+ c.relowner
+ FROM (SELECT attrelid, attname, (aclexplode(coalesce(attacl, acldefault('c', relowner)))).*
+ FROM pg_attribute a JOIN pg_class cc ON (a.attrelid = cc.oid)
+ WHERE attnum > 0
+ AND NOT attisdropped
+ ) pr_a (attrelid, attname, grantor, grantee, prtype, grantable),
+ pg_class c
+ WHERE pr_a.attrelid = c.oid
+ AND relkind IN ('r', 'v', 'f', 'p')
+ ) x,
+ pg_namespace nc,
+ pg_authid u_grantor,
+ (
+ SELECT oid, rolname FROM pg_authid
+ UNION ALL
+ SELECT 0::oid, 'PUBLIC'
+ ) AS grantee (oid, rolname)
+
+ WHERE x.relnamespace = nc.oid
+ AND x.grantee = grantee.oid
+ AND x.grantor = u_grantor.oid
+ AND x.prtype IN ('INSERT', 'SELECT', 'UPDATE', 'REFERENCES')
+ AND (pg_has_role(u_grantor.oid, 'USAGE')
+ OR pg_has_role(grantee.oid, 'USAGE')
+ OR grantee.rolname = 'PUBLIC');
+
+GRANT SELECT ON column_privileges TO PUBLIC;
+
+
+/*
+ * 5.20
+ * COLUMN_UDT_USAGE view
+ */
+
+CREATE VIEW column_udt_usage AS
+ SELECT CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(coalesce(nbt.nspname, nt.nspname) AS sql_identifier) AS udt_schema,
+ CAST(coalesce(bt.typname, t.typname) AS sql_identifier) AS udt_name,
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nc.nspname AS sql_identifier) AS table_schema,
+ CAST(c.relname AS sql_identifier) AS table_name,
+ CAST(a.attname AS sql_identifier) AS column_name
+
+ FROM pg_attribute a, pg_class c, pg_namespace nc,
+ (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid))
+ LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON (bt.typnamespace = nbt.oid))
+ ON (t.typtype = 'd' AND t.typbasetype = bt.oid)
+
+ WHERE a.attrelid = c.oid
+ AND a.atttypid = t.oid
+ AND nc.oid = c.relnamespace
+ AND a.attnum > 0 AND NOT a.attisdropped
+ AND c.relkind in ('r', 'v', 'f', 'p')
+ AND pg_has_role(coalesce(bt.typowner, t.typowner), 'USAGE');
+
+GRANT SELECT ON column_udt_usage TO PUBLIC;
+
+
+/*
+ * 5.21
+ * COLUMNS view
+ */
+
+CREATE VIEW columns AS
+ SELECT CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nc.nspname AS sql_identifier) AS table_schema,
+ CAST(c.relname AS sql_identifier) AS table_name,
+ CAST(a.attname AS sql_identifier) AS column_name,
+ CAST(a.attnum AS cardinal_number) AS ordinal_position,
+ CAST(CASE WHEN a.attgenerated = '' THEN pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS column_default,
+ CAST(CASE WHEN a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END
+ AS yes_or_no)
+ AS is_nullable,
+
+ CAST(
+ CASE WHEN t.typtype = 'd' THEN
+ CASE WHEN bt.typelem <> 0 AND bt.typlen = -1 THEN 'ARRAY'
+ WHEN nbt.nspname = 'pg_catalog' THEN format_type(t.typbasetype, null)
+ ELSE 'USER-DEFINED' END
+ ELSE
+ CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY'
+ WHEN nt.nspname = 'pg_catalog' THEN format_type(a.atttypid, null)
+ ELSE 'USER-DEFINED' END
+ END
+ AS character_data)
+ AS data_type,
+
+ CAST(
+ _pg_char_max_length(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS character_maximum_length,
+
+ CAST(
+ _pg_char_octet_length(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS character_octet_length,
+
+ CAST(
+ _pg_numeric_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS numeric_precision,
+
+ CAST(
+ _pg_numeric_precision_radix(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS numeric_precision_radix,
+
+ CAST(
+ _pg_numeric_scale(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS numeric_scale,
+
+ CAST(
+ _pg_datetime_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS cardinal_number)
+ AS datetime_precision,
+
+ CAST(
+ _pg_interval_type(_pg_truetypid(a, t), _pg_truetypmod(a, t))
+ AS character_data)
+ AS interval_type,
+ CAST(null AS cardinal_number) AS interval_precision,
+
+ CAST(null AS sql_identifier) AS character_set_catalog,
+ CAST(null AS sql_identifier) AS character_set_schema,
+ CAST(null AS sql_identifier) AS character_set_name,
+
+ CAST(CASE WHEN nco.nspname IS NOT NULL THEN current_database() END AS sql_identifier) AS collation_catalog,
+ CAST(nco.nspname AS sql_identifier) AS collation_schema,
+ CAST(co.collname AS sql_identifier) AS collation_name,
+
+ CAST(CASE WHEN t.typtype = 'd' THEN current_database() ELSE null END
+ AS sql_identifier) AS domain_catalog,
+ CAST(CASE WHEN t.typtype = 'd' THEN nt.nspname ELSE null END
+ AS sql_identifier) AS domain_schema,
+ CAST(CASE WHEN t.typtype = 'd' THEN t.typname ELSE null END
+ AS sql_identifier) AS domain_name,
+
+ CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(coalesce(nbt.nspname, nt.nspname) AS sql_identifier) AS udt_schema,
+ CAST(coalesce(bt.typname, t.typname) AS sql_identifier) AS udt_name,
+
+ CAST(null AS sql_identifier) AS scope_catalog,
+ CAST(null AS sql_identifier) AS scope_schema,
+ CAST(null AS sql_identifier) AS scope_name,
+
+ CAST(null AS cardinal_number) AS maximum_cardinality,
+ CAST(a.attnum AS sql_identifier) AS dtd_identifier,
+ CAST('NO' AS yes_or_no) AS is_self_referencing,
+
+ CAST(CASE WHEN a.attidentity IN ('a', 'd') THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_identity,
+ CAST(CASE a.attidentity WHEN 'a' THEN 'ALWAYS' WHEN 'd' THEN 'BY DEFAULT' END AS character_data) AS identity_generation,
+ CAST(seq.seqstart AS character_data) AS identity_start,
+ CAST(seq.seqincrement AS character_data) AS identity_increment,
+ CAST(seq.seqmax AS character_data) AS identity_maximum,
+ CAST(seq.seqmin AS character_data) AS identity_minimum,
+ CAST(CASE WHEN seq.seqcycle THEN 'YES' ELSE 'NO' END AS yes_or_no) AS identity_cycle,
+
+ CAST(CASE WHEN a.attgenerated <> '' THEN 'ALWAYS' ELSE 'NEVER' END AS character_data) AS is_generated,
+ CAST(CASE WHEN a.attgenerated <> '' THEN pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS generation_expression,
+
+ CAST(CASE WHEN c.relkind IN ('r', 'p') OR
+ (c.relkind IN ('v', 'f') AND
+ pg_column_is_updatable(c.oid, a.attnum, false))
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_updatable
+
+ FROM (pg_attribute a LEFT JOIN pg_attrdef ad ON attrelid = adrelid AND attnum = adnum)
+ JOIN (pg_class c JOIN pg_namespace nc ON (c.relnamespace = nc.oid)) ON a.attrelid = c.oid
+ JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON a.atttypid = t.oid
+ LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON (bt.typnamespace = nbt.oid))
+ ON (t.typtype = 'd' AND t.typbasetype = bt.oid)
+ LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid))
+ ON a.attcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default')
+ LEFT JOIN (pg_depend dep JOIN pg_sequence seq ON (dep.classid = 'pg_class'::regclass AND dep.objid = seq.seqrelid AND dep.deptype = 'i'))
+ ON (dep.refclassid = 'pg_class'::regclass AND dep.refobjid = c.oid AND dep.refobjsubid = a.attnum)
+
+ WHERE (NOT pg_is_other_temp_schema(nc.oid))
+
+ AND a.attnum > 0 AND NOT a.attisdropped
+ AND c.relkind IN ('r', 'v', 'f', 'p')
+
+ AND (pg_has_role(c.relowner, 'USAGE')
+ OR has_column_privilege(c.oid, a.attnum,
+ 'SELECT, INSERT, UPDATE, REFERENCES'));
+
+GRANT SELECT ON columns TO PUBLIC;
+
+
+/*
+ * 5.22
+ * CONSTRAINT_COLUMN_USAGE view
+ */
+
+CREATE VIEW constraint_column_usage AS
+ SELECT CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(tblschema AS sql_identifier) AS table_schema,
+ CAST(tblname AS sql_identifier) AS table_name,
+ CAST(colname AS sql_identifier) AS column_name,
+ CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(cstrschema AS sql_identifier) AS constraint_schema,
+ CAST(cstrname AS sql_identifier) AS constraint_name
+
+ FROM (
+ /* check constraints */
+ SELECT DISTINCT nr.nspname, r.relname, r.relowner, a.attname, nc.nspname, c.conname
+ FROM pg_namespace nr, pg_class r, pg_attribute a, pg_depend d, pg_namespace nc, pg_constraint c
+ WHERE nr.oid = r.relnamespace
+ AND r.oid = a.attrelid
+ AND d.refclassid = 'pg_catalog.pg_class'::regclass
+ AND d.refobjid = r.oid
+ AND d.refobjsubid = a.attnum
+ AND d.classid = 'pg_catalog.pg_constraint'::regclass
+ AND d.objid = c.oid
+ AND c.connamespace = nc.oid
+ AND c.contype = 'c'
+ AND r.relkind IN ('r', 'p')
+ AND NOT a.attisdropped
+
+ UNION ALL
+
+ /* unique/primary key/foreign key constraints */
+ SELECT nr.nspname, r.relname, r.relowner, a.attname, nc.nspname, c.conname
+ FROM pg_namespace nr, pg_class r, pg_attribute a, pg_namespace nc,
+ pg_constraint c
+ WHERE nr.oid = r.relnamespace
+ AND r.oid = a.attrelid
+ AND nc.oid = c.connamespace
+ AND r.oid = CASE c.contype WHEN 'f' THEN c.confrelid ELSE c.conrelid END
+ AND a.attnum = ANY (CASE c.contype WHEN 'f' THEN c.confkey ELSE c.conkey END)
+ AND NOT a.attisdropped
+ AND c.contype IN ('p', 'u', 'f')
+ AND r.relkind IN ('r', 'p')
+
+ ) AS x (tblschema, tblname, tblowner, colname, cstrschema, cstrname)
+
+ WHERE pg_has_role(x.tblowner, 'USAGE');
+
+GRANT SELECT ON constraint_column_usage TO PUBLIC;
+
+
+/*
+ * 5.23
+ * CONSTRAINT_PERIOD_USAGE view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.24
+ * CONSTRAINT_TABLE_USAGE view
+ */
+
+CREATE VIEW constraint_table_usage AS
+ SELECT CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nr.nspname AS sql_identifier) AS table_schema,
+ CAST(r.relname AS sql_identifier) AS table_name,
+ CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(nc.nspname AS sql_identifier) AS constraint_schema,
+ CAST(c.conname AS sql_identifier) AS constraint_name
+
+ FROM pg_constraint c, pg_namespace nc,
+ pg_class r, pg_namespace nr
+
+ WHERE c.connamespace = nc.oid AND r.relnamespace = nr.oid
+ AND ( (c.contype = 'f' AND c.confrelid = r.oid)
+ OR (c.contype IN ('p', 'u') AND c.conrelid = r.oid) )
+ AND r.relkind IN ('r', 'p')
+ AND pg_has_role(r.relowner, 'USAGE');
+
+GRANT SELECT ON constraint_table_usage TO PUBLIC;
+
+
+-- 5.25 DATA_TYPE_PRIVILEGES view appears later.
+
+
+/*
+ * 5.26
+ * DIRECT_SUPERTABLES view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.27
+ * DIRECT_SUPERTYPES view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.28
+ * DOMAIN_CONSTRAINTS view
+ */
+
+CREATE VIEW domain_constraints AS
+ SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(rs.nspname AS sql_identifier) AS constraint_schema,
+ CAST(con.conname AS sql_identifier) AS constraint_name,
+ CAST(current_database() AS sql_identifier) AS domain_catalog,
+ CAST(n.nspname AS sql_identifier) AS domain_schema,
+ CAST(t.typname AS sql_identifier) AS domain_name,
+ CAST(CASE WHEN condeferrable THEN 'YES' ELSE 'NO' END
+ AS yes_or_no) AS is_deferrable,
+ CAST(CASE WHEN condeferred THEN 'YES' ELSE 'NO' END
+ AS yes_or_no) AS initially_deferred
+ FROM pg_namespace rs, pg_namespace n, pg_constraint con, pg_type t
+ WHERE rs.oid = con.connamespace
+ AND n.oid = t.typnamespace
+ AND t.oid = con.contypid
+ AND (pg_has_role(t.typowner, 'USAGE')
+ OR has_type_privilege(t.oid, 'USAGE'));
+
+GRANT SELECT ON domain_constraints TO PUBLIC;
+
+
+/*
+ * DOMAIN_UDT_USAGE view
+ * apparently removed in SQL:2003
+ */
+
+CREATE VIEW domain_udt_usage AS
+ SELECT CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(nbt.nspname AS sql_identifier) AS udt_schema,
+ CAST(bt.typname AS sql_identifier) AS udt_name,
+ CAST(current_database() AS sql_identifier) AS domain_catalog,
+ CAST(nt.nspname AS sql_identifier) AS domain_schema,
+ CAST(t.typname AS sql_identifier) AS domain_name
+
+ FROM pg_type t, pg_namespace nt,
+ pg_type bt, pg_namespace nbt
+
+ WHERE t.typnamespace = nt.oid
+ AND t.typbasetype = bt.oid
+ AND bt.typnamespace = nbt.oid
+ AND t.typtype = 'd'
+ AND pg_has_role(bt.typowner, 'USAGE');
+
+GRANT SELECT ON domain_udt_usage TO PUBLIC;
+
+
+/*
+ * 5.29
+ * DOMAINS view
+ */
+
+CREATE VIEW domains AS
+ SELECT CAST(current_database() AS sql_identifier) AS domain_catalog,
+ CAST(nt.nspname AS sql_identifier) AS domain_schema,
+ CAST(t.typname AS sql_identifier) AS domain_name,
+
+ CAST(
+ CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY'
+ WHEN nbt.nspname = 'pg_catalog' THEN format_type(t.typbasetype, null)
+ ELSE 'USER-DEFINED' END
+ AS character_data)
+ AS data_type,
+
+ CAST(
+ _pg_char_max_length(t.typbasetype, t.typtypmod)
+ AS cardinal_number)
+ AS character_maximum_length,
+
+ CAST(
+ _pg_char_octet_length(t.typbasetype, t.typtypmod)
+ AS cardinal_number)
+ AS character_octet_length,
+
+ CAST(null AS sql_identifier) AS character_set_catalog,
+ CAST(null AS sql_identifier) AS character_set_schema,
+ CAST(null AS sql_identifier) AS character_set_name,
+
+ CAST(CASE WHEN nco.nspname IS NOT NULL THEN current_database() END AS sql_identifier) AS collation_catalog,
+ CAST(nco.nspname AS sql_identifier) AS collation_schema,
+ CAST(co.collname AS sql_identifier) AS collation_name,
+
+ CAST(
+ _pg_numeric_precision(t.typbasetype, t.typtypmod)
+ AS cardinal_number)
+ AS numeric_precision,
+
+ CAST(
+ _pg_numeric_precision_radix(t.typbasetype, t.typtypmod)
+ AS cardinal_number)
+ AS numeric_precision_radix,
+
+ CAST(
+ _pg_numeric_scale(t.typbasetype, t.typtypmod)
+ AS cardinal_number)
+ AS numeric_scale,
+
+ CAST(
+ _pg_datetime_precision(t.typbasetype, t.typtypmod)
+ AS cardinal_number)
+ AS datetime_precision,
+
+ CAST(
+ _pg_interval_type(t.typbasetype, t.typtypmod)
+ AS character_data)
+ AS interval_type,
+ CAST(null AS cardinal_number) AS interval_precision,
+
+ CAST(t.typdefault AS character_data) AS domain_default,
+
+ CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(nbt.nspname AS sql_identifier) AS udt_schema,
+ CAST(bt.typname AS sql_identifier) AS udt_name,
+
+ CAST(null AS sql_identifier) AS scope_catalog,
+ CAST(null AS sql_identifier) AS scope_schema,
+ CAST(null AS sql_identifier) AS scope_name,
+
+ CAST(null AS cardinal_number) AS maximum_cardinality,
+ CAST(1 AS sql_identifier) AS dtd_identifier
+
+ FROM (pg_type t JOIN pg_namespace nt ON t.typnamespace = nt.oid)
+ JOIN (pg_type bt JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid)
+ ON (t.typbasetype = bt.oid AND t.typtype = 'd')
+ LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid))
+ ON t.typcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default')
+
+ WHERE (pg_has_role(t.typowner, 'USAGE')
+ OR has_type_privilege(t.oid, 'USAGE'));
+
+GRANT SELECT ON domains TO PUBLIC;
+
+
+-- 5.30 ELEMENT_TYPES view appears later.
+
+
+/*
+ * 5.31
+ * ENABLED_ROLES view
+ */
+
+CREATE VIEW enabled_roles AS
+ SELECT CAST(a.rolname AS sql_identifier) AS role_name
+ FROM pg_authid a
+ WHERE pg_has_role(a.oid, 'USAGE');
+
+GRANT SELECT ON enabled_roles TO PUBLIC;
+
+
+/*
+ * 5.32
+ * FIELDS view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.33
+ * KEY_COLUMN_USAGE view
+ */
+
+CREATE VIEW key_column_usage AS
+ SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(nc_nspname AS sql_identifier) AS constraint_schema,
+ CAST(conname AS sql_identifier) AS constraint_name,
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nr_nspname AS sql_identifier) AS table_schema,
+ CAST(relname AS sql_identifier) AS table_name,
+ CAST(a.attname AS sql_identifier) AS column_name,
+ CAST((ss.x).n AS cardinal_number) AS ordinal_position,
+ CAST(CASE WHEN contype = 'f' THEN
+ _pg_index_position(ss.conindid, ss.confkey[(ss.x).n])
+ ELSE NULL
+ END AS cardinal_number)
+ AS position_in_unique_constraint
+ FROM pg_attribute a,
+ (SELECT r.oid AS roid, r.relname, r.relowner,
+ nc.nspname AS nc_nspname, nr.nspname AS nr_nspname,
+ c.oid AS coid, c.conname, c.contype, c.conindid,
+ c.confkey, c.confrelid,
+ _pg_expandarray(c.conkey) AS x
+ FROM pg_namespace nr, pg_class r, pg_namespace nc,
+ pg_constraint c
+ WHERE nr.oid = r.relnamespace
+ AND r.oid = c.conrelid
+ AND nc.oid = c.connamespace
+ AND c.contype IN ('p', 'u', 'f')
+ AND r.relkind IN ('r', 'p')
+ AND (NOT pg_is_other_temp_schema(nr.oid)) ) AS ss
+ WHERE ss.roid = a.attrelid
+ AND a.attnum = (ss.x).x
+ AND NOT a.attisdropped
+ AND (pg_has_role(relowner, 'USAGE')
+ OR has_column_privilege(roid, a.attnum,
+ 'SELECT, INSERT, UPDATE, REFERENCES'));
+
+GRANT SELECT ON key_column_usage TO PUBLIC;
+
+
+/*
+ * 5.34
+ * KEY_PERIOD_USAGE view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.35
+ * METHOD_SPECIFICATION_PARAMETERS view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.36
+ * METHOD_SPECIFICATIONS view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.37
+ * PARAMETERS view
+ */
+
+CREATE VIEW parameters AS
+ SELECT CAST(current_database() AS sql_identifier) AS specific_catalog,
+ CAST(n_nspname AS sql_identifier) AS specific_schema,
+ CAST(nameconcatoid(proname, p_oid) AS sql_identifier) AS specific_name,
+ CAST((ss.x).n AS cardinal_number) AS ordinal_position,
+ CAST(
+ CASE WHEN proargmodes IS NULL THEN 'IN'
+ WHEN proargmodes[(ss.x).n] = 'i' THEN 'IN'
+ WHEN proargmodes[(ss.x).n] = 'o' THEN 'OUT'
+ WHEN proargmodes[(ss.x).n] = 'b' THEN 'INOUT'
+ WHEN proargmodes[(ss.x).n] = 'v' THEN 'IN'
+ WHEN proargmodes[(ss.x).n] = 't' THEN 'OUT'
+ END AS character_data) AS parameter_mode,
+ CAST('NO' AS yes_or_no) AS is_result,
+ CAST('NO' AS yes_or_no) AS as_locator,
+ CAST(NULLIF(proargnames[(ss.x).n], '') AS sql_identifier) AS parameter_name,
+ CAST(
+ CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY'
+ WHEN nt.nspname = 'pg_catalog' THEN format_type(t.oid, null)
+ ELSE 'USER-DEFINED' END AS character_data)
+ AS data_type,
+ CAST(null AS cardinal_number) AS character_maximum_length,
+ CAST(null AS cardinal_number) AS character_octet_length,
+ CAST(null AS sql_identifier) AS character_set_catalog,
+ CAST(null AS sql_identifier) AS character_set_schema,
+ CAST(null AS sql_identifier) AS character_set_name,
+ CAST(null AS sql_identifier) AS collation_catalog,
+ CAST(null AS sql_identifier) AS collation_schema,
+ CAST(null AS sql_identifier) AS collation_name,
+ CAST(null AS cardinal_number) AS numeric_precision,
+ CAST(null AS cardinal_number) AS numeric_precision_radix,
+ CAST(null AS cardinal_number) AS numeric_scale,
+ CAST(null AS cardinal_number) AS datetime_precision,
+ CAST(null AS character_data) AS interval_type,
+ CAST(null AS cardinal_number) AS interval_precision,
+ CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(nt.nspname AS sql_identifier) AS udt_schema,
+ CAST(t.typname AS sql_identifier) AS udt_name,
+ CAST(null AS sql_identifier) AS scope_catalog,
+ CAST(null AS sql_identifier) AS scope_schema,
+ CAST(null AS sql_identifier) AS scope_name,
+ CAST(null AS cardinal_number) AS maximum_cardinality,
+ CAST((ss.x).n AS sql_identifier) AS dtd_identifier,
+ CAST(
+ CASE WHEN pg_has_role(proowner, 'USAGE')
+ THEN pg_get_function_arg_default(p_oid, (ss.x).n)
+ ELSE NULL END
+ AS character_data) AS parameter_default
+
+ FROM pg_type t, pg_namespace nt,
+ (SELECT n.nspname AS n_nspname, p.proname, p.oid AS p_oid, p.proowner,
+ p.proargnames, p.proargmodes,
+ _pg_expandarray(coalesce(p.proallargtypes, p.proargtypes::oid[])) AS x
+ FROM pg_namespace n, pg_proc p
+ WHERE n.oid = p.pronamespace
+ AND (pg_has_role(p.proowner, 'USAGE') OR
+ has_function_privilege(p.oid, 'EXECUTE'))) AS ss
+ WHERE t.oid = (ss.x).x AND t.typnamespace = nt.oid;
+
+GRANT SELECT ON parameters TO PUBLIC;
+
+
+/*
+ * 5.38
+ * PERIODS view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.39
+ * PRIVATE_PARAMETERS view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.40
+ * REFERENCED_TYPES view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.41
+ * REFERENTIAL_CONSTRAINTS view
+ */
+
+CREATE VIEW referential_constraints AS
+ SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(ncon.nspname AS sql_identifier) AS constraint_schema,
+ CAST(con.conname AS sql_identifier) AS constraint_name,
+ CAST(
+ CASE WHEN npkc.nspname IS NULL THEN NULL
+ ELSE current_database() END
+ AS sql_identifier) AS unique_constraint_catalog,
+ CAST(npkc.nspname AS sql_identifier) AS unique_constraint_schema,
+ CAST(pkc.conname AS sql_identifier) AS unique_constraint_name,
+
+ CAST(
+ CASE con.confmatchtype WHEN 'f' THEN 'FULL'
+ WHEN 'p' THEN 'PARTIAL'
+ WHEN 's' THEN 'NONE' END
+ AS character_data) AS match_option,
+
+ CAST(
+ CASE con.confupdtype WHEN 'c' THEN 'CASCADE'
+ WHEN 'n' THEN 'SET NULL'
+ WHEN 'd' THEN 'SET DEFAULT'
+ WHEN 'r' THEN 'RESTRICT'
+ WHEN 'a' THEN 'NO ACTION' END
+ AS character_data) AS update_rule,
+
+ CAST(
+ CASE con.confdeltype WHEN 'c' THEN 'CASCADE'
+ WHEN 'n' THEN 'SET NULL'
+ WHEN 'd' THEN 'SET DEFAULT'
+ WHEN 'r' THEN 'RESTRICT'
+ WHEN 'a' THEN 'NO ACTION' END
+ AS character_data) AS delete_rule
+
+ FROM (pg_namespace ncon
+ INNER JOIN pg_constraint con ON ncon.oid = con.connamespace
+ INNER JOIN pg_class c ON con.conrelid = c.oid AND con.contype = 'f')
+ LEFT JOIN pg_depend d1 -- find constraint's dependency on an index
+ ON d1.objid = con.oid AND d1.classid = 'pg_constraint'::regclass
+ AND d1.refclassid = 'pg_class'::regclass AND d1.refobjsubid = 0
+ LEFT JOIN pg_depend d2 -- find pkey/unique constraint for that index
+ ON d2.refclassid = 'pg_constraint'::regclass
+ AND d2.classid = 'pg_class'::regclass
+ AND d2.objid = d1.refobjid AND d2.objsubid = 0
+ AND d2.deptype = 'i'
+ LEFT JOIN pg_constraint pkc ON pkc.oid = d2.refobjid
+ AND pkc.contype IN ('p', 'u')
+ AND pkc.conrelid = con.confrelid
+ LEFT JOIN pg_namespace npkc ON pkc.connamespace = npkc.oid
+
+ WHERE pg_has_role(c.relowner, 'USAGE')
+ -- SELECT privilege omitted, per SQL standard
+ OR has_table_privilege(c.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(c.oid, 'INSERT, UPDATE, REFERENCES') ;
+
+GRANT SELECT ON referential_constraints TO PUBLIC;
+
+
+/*
+ * 5.42
+ * ROLE_COLUMN_GRANTS view
+ */
+
+CREATE VIEW role_column_grants AS
+ SELECT grantor,
+ grantee,
+ table_catalog,
+ table_schema,
+ table_name,
+ column_name,
+ privilege_type,
+ is_grantable
+ FROM column_privileges
+ WHERE grantor IN (SELECT role_name FROM enabled_roles)
+ OR grantee IN (SELECT role_name FROM enabled_roles);
+
+GRANT SELECT ON role_column_grants TO PUBLIC;
+
+
+-- 5.43 ROLE_ROUTINE_GRANTS view is based on 5.50 ROUTINE_PRIVILEGES and is defined there instead.
+
+
+-- 5.44 ROLE_TABLE_GRANTS view is based on 5.63 TABLE_PRIVILEGES and is defined there instead.
+
+
+/*
+ * 5.45
+ * ROLE_TABLE_METHOD_GRANTS view
+ */
+
+-- feature not supported
+
+
+
+-- 5.46 ROLE_USAGE_GRANTS view is based on 5.75 USAGE_PRIVILEGES and is defined there instead.
+
+
+-- 5.47 ROLE_UDT_GRANTS view is based on 5.74 UDT_PRIVILEGES and is defined there instead.
+
+
+/*
+ * 5.48
+ * ROUTINE_COLUMN_USAGE view
+ */
+
+-- not tracked by PostgreSQL
+
+
+/*
+ * 5.49
+ * ROUTINE_PERIOD_USAGE view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.50
+ * ROUTINE_PRIVILEGES view
+ */
+
+CREATE VIEW routine_privileges AS
+ SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
+ CAST(grantee.rolname AS sql_identifier) AS grantee,
+ CAST(current_database() AS sql_identifier) AS specific_catalog,
+ CAST(n.nspname AS sql_identifier) AS specific_schema,
+ CAST(nameconcatoid(p.proname, p.oid) AS sql_identifier) AS specific_name,
+ CAST(current_database() AS sql_identifier) AS routine_catalog,
+ CAST(n.nspname AS sql_identifier) AS routine_schema,
+ CAST(p.proname AS sql_identifier) AS routine_name,
+ CAST('EXECUTE' AS character_data) AS privilege_type,
+ CAST(
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, p.proowner, 'USAGE')
+ OR p.grantable
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_grantable
+
+ FROM (
+ SELECT oid, proname, proowner, pronamespace, (aclexplode(coalesce(proacl, acldefault('f', proowner)))).* FROM pg_proc
+ ) p (oid, proname, proowner, pronamespace, grantor, grantee, prtype, grantable),
+ pg_namespace n,
+ pg_authid u_grantor,
+ (
+ SELECT oid, rolname FROM pg_authid
+ UNION ALL
+ SELECT 0::oid, 'PUBLIC'
+ ) AS grantee (oid, rolname)
+
+ WHERE p.pronamespace = n.oid
+ AND grantee.oid = p.grantee
+ AND u_grantor.oid = p.grantor
+ AND p.prtype IN ('EXECUTE')
+ AND (pg_has_role(u_grantor.oid, 'USAGE')
+ OR pg_has_role(grantee.oid, 'USAGE')
+ OR grantee.rolname = 'PUBLIC');
+
+GRANT SELECT ON routine_privileges TO PUBLIC;
+
+
+/*
+ * 5.42
+ * ROLE_ROUTINE_GRANTS view
+ */
+
+CREATE VIEW role_routine_grants AS
+ SELECT grantor,
+ grantee,
+ specific_catalog,
+ specific_schema,
+ specific_name,
+ routine_catalog,
+ routine_schema,
+ routine_name,
+ privilege_type,
+ is_grantable
+ FROM routine_privileges
+ WHERE grantor IN (SELECT role_name FROM enabled_roles)
+ OR grantee IN (SELECT role_name FROM enabled_roles);
+
+GRANT SELECT ON role_routine_grants TO PUBLIC;
+
+
+/*
+ * 5.51
+ * ROUTINE_ROUTINE_USAGE view
+ */
+
+-- not tracked by PostgreSQL
+
+
+/*
+ * 5.52
+ * ROUTINE_SEQUENCE_USAGE view
+ */
+
+-- not tracked by PostgreSQL
+
+
+/*
+ * 5.53
+ * ROUTINE_TABLE_USAGE view
+ */
+
+-- not tracked by PostgreSQL
+
+
+/*
+ * 5.54
+ * ROUTINES view
+ */
+
+CREATE VIEW routines AS
+ SELECT CAST(current_database() AS sql_identifier) AS specific_catalog,
+ CAST(n.nspname AS sql_identifier) AS specific_schema,
+ CAST(nameconcatoid(p.proname, p.oid) AS sql_identifier) AS specific_name,
+ CAST(current_database() AS sql_identifier) AS routine_catalog,
+ CAST(n.nspname AS sql_identifier) AS routine_schema,
+ CAST(p.proname AS sql_identifier) AS routine_name,
+ CAST(CASE p.prokind WHEN 'f' THEN 'FUNCTION' WHEN 'p' THEN 'PROCEDURE' END
+ AS character_data) AS routine_type,
+ CAST(null AS sql_identifier) AS module_catalog,
+ CAST(null AS sql_identifier) AS module_schema,
+ CAST(null AS sql_identifier) AS module_name,
+ CAST(null AS sql_identifier) AS udt_catalog,
+ CAST(null AS sql_identifier) AS udt_schema,
+ CAST(null AS sql_identifier) AS udt_name,
+
+ CAST(
+ CASE WHEN p.prokind = 'p' THEN NULL
+ WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY'
+ WHEN nt.nspname = 'pg_catalog' THEN format_type(t.oid, null)
+ ELSE 'USER-DEFINED' END AS character_data)
+ AS data_type,
+ CAST(null AS cardinal_number) AS character_maximum_length,
+ CAST(null AS cardinal_number) AS character_octet_length,
+ CAST(null AS sql_identifier) AS character_set_catalog,
+ CAST(null AS sql_identifier) AS character_set_schema,
+ CAST(null AS sql_identifier) AS character_set_name,
+ CAST(null AS sql_identifier) AS collation_catalog,
+ CAST(null AS sql_identifier) AS collation_schema,
+ CAST(null AS sql_identifier) AS collation_name,
+ CAST(null AS cardinal_number) AS numeric_precision,
+ CAST(null AS cardinal_number) AS numeric_precision_radix,
+ CAST(null AS cardinal_number) AS numeric_scale,
+ CAST(null AS cardinal_number) AS datetime_precision,
+ CAST(null AS character_data) AS interval_type,
+ CAST(null AS cardinal_number) AS interval_precision,
+ CAST(CASE WHEN nt.nspname IS NOT NULL THEN current_database() END AS sql_identifier) AS type_udt_catalog,
+ CAST(nt.nspname AS sql_identifier) AS type_udt_schema,
+ CAST(t.typname AS sql_identifier) AS type_udt_name,
+ CAST(null AS sql_identifier) AS scope_catalog,
+ CAST(null AS sql_identifier) AS scope_schema,
+ CAST(null AS sql_identifier) AS scope_name,
+ CAST(null AS cardinal_number) AS maximum_cardinality,
+ CAST(CASE WHEN p.prokind <> 'p' THEN 0 END AS sql_identifier) AS dtd_identifier,
+
+ CAST(CASE WHEN l.lanname = 'sql' THEN 'SQL' ELSE 'EXTERNAL' END AS character_data)
+ AS routine_body,
+ CAST(
+ CASE WHEN pg_has_role(p.proowner, 'USAGE') THEN p.prosrc ELSE null END
+ AS character_data) AS routine_definition,
+ CAST(
+ CASE WHEN l.lanname = 'c' THEN p.prosrc ELSE null END
+ AS character_data) AS external_name,
+ CAST(upper(l.lanname) AS character_data) AS external_language,
+
+ CAST('GENERAL' AS character_data) AS parameter_style,
+ CAST(CASE WHEN p.provolatile = 'i' THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_deterministic,
+ CAST('MODIFIES' AS character_data) AS sql_data_access,
+ CAST(CASE WHEN p.prokind <> 'p' THEN
+ CASE WHEN p.proisstrict THEN 'YES' ELSE 'NO' END END AS yes_or_no) AS is_null_call,
+ CAST(null AS character_data) AS sql_path,
+ CAST('YES' AS yes_or_no) AS schema_level_routine,
+ CAST(0 AS cardinal_number) AS max_dynamic_result_sets,
+ CAST(null AS yes_or_no) AS is_user_defined_cast,
+ CAST(null AS yes_or_no) AS is_implicitly_invocable,
+ CAST(CASE WHEN p.prosecdef THEN 'DEFINER' ELSE 'INVOKER' END AS character_data) AS security_type,
+ CAST(null AS sql_identifier) AS to_sql_specific_catalog,
+ CAST(null AS sql_identifier) AS to_sql_specific_schema,
+ CAST(null AS sql_identifier) AS to_sql_specific_name,
+ CAST('NO' AS yes_or_no) AS as_locator,
+ CAST(null AS time_stamp) AS created,
+ CAST(null AS time_stamp) AS last_altered,
+ CAST(null AS yes_or_no) AS new_savepoint_level,
+ CAST('NO' AS yes_or_no) AS is_udt_dependent,
+
+ CAST(null AS character_data) AS result_cast_from_data_type,
+ CAST(null AS yes_or_no) AS result_cast_as_locator,
+ CAST(null AS cardinal_number) AS result_cast_char_max_length,
+ CAST(null AS cardinal_number) AS result_cast_char_octet_length,
+ CAST(null AS sql_identifier) AS result_cast_char_set_catalog,
+ CAST(null AS sql_identifier) AS result_cast_char_set_schema,
+ CAST(null AS sql_identifier) AS result_cast_char_set_name,
+ CAST(null AS sql_identifier) AS result_cast_collation_catalog,
+ CAST(null AS sql_identifier) AS result_cast_collation_schema,
+ CAST(null AS sql_identifier) AS result_cast_collation_name,
+ CAST(null AS cardinal_number) AS result_cast_numeric_precision,
+ CAST(null AS cardinal_number) AS result_cast_numeric_precision_radix,
+ CAST(null AS cardinal_number) AS result_cast_numeric_scale,
+ CAST(null AS cardinal_number) AS result_cast_datetime_precision,
+ CAST(null AS character_data) AS result_cast_interval_type,
+ CAST(null AS cardinal_number) AS result_cast_interval_precision,
+ CAST(null AS sql_identifier) AS result_cast_type_udt_catalog,
+ CAST(null AS sql_identifier) AS result_cast_type_udt_schema,
+ CAST(null AS sql_identifier) AS result_cast_type_udt_name,
+ CAST(null AS sql_identifier) AS result_cast_scope_catalog,
+ CAST(null AS sql_identifier) AS result_cast_scope_schema,
+ CAST(null AS sql_identifier) AS result_cast_scope_name,
+ CAST(null AS cardinal_number) AS result_cast_maximum_cardinality,
+ CAST(null AS sql_identifier) AS result_cast_dtd_identifier
+
+ FROM (pg_namespace n
+ JOIN pg_proc p ON n.oid = p.pronamespace
+ JOIN pg_language l ON p.prolang = l.oid)
+ LEFT JOIN
+ (pg_type t JOIN pg_namespace nt ON t.typnamespace = nt.oid)
+ ON p.prorettype = t.oid AND p.prokind <> 'p'
+
+ WHERE (pg_has_role(p.proowner, 'USAGE')
+ OR has_function_privilege(p.oid, 'EXECUTE'));
+
+GRANT SELECT ON routines TO PUBLIC;
+
+
+/*
+ * 5.55
+ * SCHEMATA view
+ */
+
+CREATE VIEW schemata AS
+ SELECT CAST(current_database() AS sql_identifier) AS catalog_name,
+ CAST(n.nspname AS sql_identifier) AS schema_name,
+ CAST(u.rolname AS sql_identifier) AS schema_owner,
+ CAST(null AS sql_identifier) AS default_character_set_catalog,
+ CAST(null AS sql_identifier) AS default_character_set_schema,
+ CAST(null AS sql_identifier) AS default_character_set_name,
+ CAST(null AS character_data) AS sql_path
+ FROM pg_namespace n, pg_authid u
+ WHERE n.nspowner = u.oid
+ AND (pg_has_role(n.nspowner, 'USAGE')
+ OR has_schema_privilege(n.oid, 'CREATE, USAGE'));
+
+GRANT SELECT ON schemata TO PUBLIC;
+
+
+/*
+ * 5.56
+ * SEQUENCES view
+ */
+
+CREATE VIEW sequences AS
+ SELECT CAST(current_database() AS sql_identifier) AS sequence_catalog,
+ CAST(nc.nspname AS sql_identifier) AS sequence_schema,
+ CAST(c.relname AS sql_identifier) AS sequence_name,
+ CAST(format_type(s.seqtypid, null) AS character_data) AS data_type,
+ CAST(_pg_numeric_precision(s.seqtypid, -1) AS cardinal_number) AS numeric_precision,
+ CAST(2 AS cardinal_number) AS numeric_precision_radix,
+ CAST(0 AS cardinal_number) AS numeric_scale,
+ CAST(s.seqstart AS character_data) AS start_value,
+ CAST(s.seqmin AS character_data) AS minimum_value,
+ CAST(s.seqmax AS character_data) AS maximum_value,
+ CAST(s.seqincrement AS character_data) AS increment,
+ CAST(CASE WHEN s.seqcycle THEN 'YES' ELSE 'NO' END AS yes_or_no) AS cycle_option
+ FROM pg_namespace nc, pg_class c, pg_sequence s
+ WHERE c.relnamespace = nc.oid
+ AND c.relkind = 'S'
+ AND NOT EXISTS (SELECT 1 FROM pg_depend WHERE classid = 'pg_class'::regclass AND objid = c.oid AND deptype = 'i')
+ AND (NOT pg_is_other_temp_schema(nc.oid))
+ AND c.oid = s.seqrelid
+ AND (pg_has_role(c.relowner, 'USAGE')
+ OR has_sequence_privilege(c.oid, 'SELECT, UPDATE, USAGE') );
+
+GRANT SELECT ON sequences TO PUBLIC;
+
+
+/*
+ * 5.57
+ * SQL_FEATURES table
+ */
+
+CREATE TABLE sql_features (
+ feature_id character_data,
+ feature_name character_data,
+ sub_feature_id character_data,
+ sub_feature_name character_data,
+ is_supported yes_or_no,
+ is_verified_by character_data,
+ comments character_data
+);
+
+-- Will be filled with external data by initdb.
+
+GRANT SELECT ON sql_features TO PUBLIC;
+
+
+/*
+ * 5.58
+ * SQL_IMPLEMENTATION_INFO table
+ */
+
+-- Note: Implementation information items are defined in ISO/IEC 9075-3:2008,
+-- clause 9.1.
+
+CREATE TABLE sql_implementation_info (
+ implementation_info_id character_data,
+ implementation_info_name character_data,
+ integer_value cardinal_number,
+ character_value character_data,
+ comments character_data
+);
+
+INSERT INTO sql_implementation_info VALUES ('10003', 'CATALOG NAME', NULL, 'Y', NULL);
+INSERT INTO sql_implementation_info VALUES ('10004', 'COLLATING SEQUENCE', NULL, (SELECT default_collate_name FROM character_sets), NULL);
+INSERT INTO sql_implementation_info VALUES ('23', 'CURSOR COMMIT BEHAVIOR', 1, NULL, 'close cursors and retain prepared statements');
+INSERT INTO sql_implementation_info VALUES ('2', 'DATA SOURCE NAME', NULL, '', NULL);
+INSERT INTO sql_implementation_info VALUES ('17', 'DBMS NAME', NULL, (select trim(trailing ' ' from substring(version() from '^[^0-9]*'))), NULL);
+INSERT INTO sql_implementation_info VALUES ('18', 'DBMS VERSION', NULL, '???', NULL); -- filled by initdb
+INSERT INTO sql_implementation_info VALUES ('26', 'DEFAULT TRANSACTION ISOLATION', 2, NULL, 'READ COMMITTED; user-settable');
+INSERT INTO sql_implementation_info VALUES ('28', 'IDENTIFIER CASE', 3, NULL, 'stored in mixed case - case sensitive');
+INSERT INTO sql_implementation_info VALUES ('85', 'NULL COLLATION', 0, NULL, 'nulls higher than non-nulls');
+INSERT INTO sql_implementation_info VALUES ('13', 'SERVER NAME', NULL, '', NULL);
+INSERT INTO sql_implementation_info VALUES ('94', 'SPECIAL CHARACTERS', NULL, '', 'all non-ASCII characters allowed');
+INSERT INTO sql_implementation_info VALUES ('46', 'TRANSACTION CAPABLE', 2, NULL, 'both DML and DDL');
+
+GRANT SELECT ON sql_implementation_info TO PUBLIC;
+
+
+/*
+ * 5.59
+ * SQL_PARTS table
+ */
+
+CREATE TABLE sql_parts (
+ feature_id character_data,
+ feature_name character_data,
+ is_supported yes_or_no,
+ is_verified_by character_data,
+ comments character_data
+);
+
+INSERT INTO sql_parts VALUES ('1', 'Framework (SQL/Framework)', 'NO', NULL, '');
+INSERT INTO sql_parts VALUES ('2', 'Foundation (SQL/Foundation)', 'NO', NULL, '');
+INSERT INTO sql_parts VALUES ('3', 'Call-Level Interface (SQL/CLI)', 'NO', NULL, '');
+INSERT INTO sql_parts VALUES ('4', 'Persistent Stored Modules (SQL/PSM)', 'NO', NULL, '');
+INSERT INTO sql_parts VALUES ('9', 'Management of External Data (SQL/MED)', 'NO', NULL, '');
+INSERT INTO sql_parts VALUES ('10', 'Object Language Bindings (SQL/OLB)', 'NO', NULL, '');
+INSERT INTO sql_parts VALUES ('11', 'Information and Definition Schema (SQL/Schemata)', 'NO', NULL, '');
+INSERT INTO sql_parts VALUES ('13', 'Routines and Types Using the Java Programming Language (SQL/JRT)', 'NO', NULL, '');
+INSERT INTO sql_parts VALUES ('14', 'XML-Related Specifications (SQL/XML)', 'NO', NULL, '');
+INSERT INTO sql_parts VALUES ('15', 'Multi-Dimensional Arrays (SQL/MDA)', 'NO', NULL, '');
+
+
+/*
+ * 5.60
+ * SQL_SIZING table
+ */
+
+-- Note: Sizing items are defined in ISO/IEC 9075-3:2008, clause 9.2.
+
+CREATE TABLE sql_sizing (
+ sizing_id cardinal_number,
+ sizing_name character_data,
+ supported_value cardinal_number,
+ comments character_data
+);
+
+INSERT INTO sql_sizing VALUES (34, 'MAXIMUM CATALOG NAME LENGTH', 63, NULL);
+INSERT INTO sql_sizing VALUES (30, 'MAXIMUM COLUMN NAME LENGTH', 63, NULL);
+INSERT INTO sql_sizing VALUES (97, 'MAXIMUM COLUMNS IN GROUP BY', 0, NULL);
+INSERT INTO sql_sizing VALUES (99, 'MAXIMUM COLUMNS IN ORDER BY', 0, NULL);
+INSERT INTO sql_sizing VALUES (100, 'MAXIMUM COLUMNS IN SELECT', 1664, NULL); -- match MaxTupleAttributeNumber
+INSERT INTO sql_sizing VALUES (101, 'MAXIMUM COLUMNS IN TABLE', 1600, NULL); -- match MaxHeapAttributeNumber
+INSERT INTO sql_sizing VALUES (1, 'MAXIMUM CONCURRENT ACTIVITIES', 0, NULL);
+INSERT INTO sql_sizing VALUES (31, 'MAXIMUM CURSOR NAME LENGTH', 63, NULL);
+INSERT INTO sql_sizing VALUES (0, 'MAXIMUM DRIVER CONNECTIONS', NULL, NULL);
+INSERT INTO sql_sizing VALUES (10005, 'MAXIMUM IDENTIFIER LENGTH', 63, NULL);
+INSERT INTO sql_sizing VALUES (32, 'MAXIMUM SCHEMA NAME LENGTH', 63, NULL);
+INSERT INTO sql_sizing VALUES (20000, 'MAXIMUM STATEMENT OCTETS', 0, NULL);
+INSERT INTO sql_sizing VALUES (20001, 'MAXIMUM STATEMENT OCTETS DATA', 0, NULL);
+INSERT INTO sql_sizing VALUES (20002, 'MAXIMUM STATEMENT OCTETS SCHEMA', 0, NULL);
+INSERT INTO sql_sizing VALUES (35, 'MAXIMUM TABLE NAME LENGTH', 63, NULL);
+INSERT INTO sql_sizing VALUES (106, 'MAXIMUM TABLES IN SELECT', 0, NULL);
+INSERT INTO sql_sizing VALUES (107, 'MAXIMUM USER NAME LENGTH', 63, NULL);
+INSERT INTO sql_sizing VALUES (25000, 'MAXIMUM CURRENT DEFAULT TRANSFORM GROUP LENGTH', NULL, NULL);
+INSERT INTO sql_sizing VALUES (25001, 'MAXIMUM CURRENT TRANSFORM GROUP LENGTH', NULL, NULL);
+INSERT INTO sql_sizing VALUES (25002, 'MAXIMUM CURRENT PATH LENGTH', 0, NULL);
+INSERT INTO sql_sizing VALUES (25003, 'MAXIMUM CURRENT ROLE LENGTH', NULL, NULL);
+INSERT INTO sql_sizing VALUES (25004, 'MAXIMUM SESSION USER LENGTH', 63, NULL);
+INSERT INTO sql_sizing VALUES (25005, 'MAXIMUM SYSTEM USER LENGTH', 63, NULL);
+
+UPDATE sql_sizing
+ SET supported_value = (SELECT typlen-1 FROM pg_catalog.pg_type WHERE typname = 'name'),
+ comments = 'Might be less, depending on character set.'
+ WHERE supported_value = 63;
+
+GRANT SELECT ON sql_sizing TO PUBLIC;
+
+
+/*
+ * 5.61
+ * TABLE_CONSTRAINTS view
+ */
+
+CREATE VIEW table_constraints AS
+ SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(nc.nspname AS sql_identifier) AS constraint_schema,
+ CAST(c.conname AS sql_identifier) AS constraint_name,
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nr.nspname AS sql_identifier) AS table_schema,
+ CAST(r.relname AS sql_identifier) AS table_name,
+ CAST(
+ CASE c.contype WHEN 'c' THEN 'CHECK'
+ WHEN 'f' THEN 'FOREIGN KEY'
+ WHEN 'p' THEN 'PRIMARY KEY'
+ WHEN 'u' THEN 'UNIQUE' END
+ AS character_data) AS constraint_type,
+ CAST(CASE WHEN c.condeferrable THEN 'YES' ELSE 'NO' END AS yes_or_no)
+ AS is_deferrable,
+ CAST(CASE WHEN c.condeferred THEN 'YES' ELSE 'NO' END AS yes_or_no)
+ AS initially_deferred,
+ CAST('YES' AS yes_or_no) AS enforced
+
+ FROM pg_namespace nc,
+ pg_namespace nr,
+ pg_constraint c,
+ pg_class r
+
+ WHERE nc.oid = c.connamespace AND nr.oid = r.relnamespace
+ AND c.conrelid = r.oid
+ AND c.contype NOT IN ('t', 'x') -- ignore nonstandard constraints
+ AND r.relkind IN ('r', 'p')
+ AND (NOT pg_is_other_temp_schema(nr.oid))
+ AND (pg_has_role(r.relowner, 'USAGE')
+ -- SELECT privilege omitted, per SQL standard
+ OR has_table_privilege(r.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(r.oid, 'INSERT, UPDATE, REFERENCES') )
+
+ UNION ALL
+
+ -- not-null constraints
+
+ SELECT CAST(current_database() AS sql_identifier) AS constraint_catalog,
+ CAST(nr.nspname AS sql_identifier) AS constraint_schema,
+ CAST(CAST(nr.oid AS text) || '_' || CAST(r.oid AS text) || '_' || CAST(a.attnum AS text) || '_not_null' AS sql_identifier) AS constraint_name, -- XXX
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nr.nspname AS sql_identifier) AS table_schema,
+ CAST(r.relname AS sql_identifier) AS table_name,
+ CAST('CHECK' AS character_data) AS constraint_type,
+ CAST('NO' AS yes_or_no) AS is_deferrable,
+ CAST('NO' AS yes_or_no) AS initially_deferred,
+ CAST('YES' AS yes_or_no) AS enforced
+
+ FROM pg_namespace nr,
+ pg_class r,
+ pg_attribute a
+
+ WHERE nr.oid = r.relnamespace
+ AND r.oid = a.attrelid
+ AND a.attnotnull
+ AND a.attnum > 0
+ AND NOT a.attisdropped
+ AND r.relkind IN ('r', 'p')
+ AND (NOT pg_is_other_temp_schema(nr.oid))
+ AND (pg_has_role(r.relowner, 'USAGE')
+ -- SELECT privilege omitted, per SQL standard
+ OR has_table_privilege(r.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(r.oid, 'INSERT, UPDATE, REFERENCES') );
+
+GRANT SELECT ON table_constraints TO PUBLIC;
+
+
+/*
+ * 5.62
+ * TABLE_METHOD_PRIVILEGES view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.63
+ * TABLE_PRIVILEGES view
+ */
+
+CREATE VIEW table_privileges AS
+ SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
+ CAST(grantee.rolname AS sql_identifier) AS grantee,
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nc.nspname AS sql_identifier) AS table_schema,
+ CAST(c.relname AS sql_identifier) AS table_name,
+ CAST(c.prtype AS character_data) AS privilege_type,
+ CAST(
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, c.relowner, 'USAGE')
+ OR c.grantable
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_grantable,
+ CAST(CASE WHEN c.prtype = 'SELECT' THEN 'YES' ELSE 'NO' END AS yes_or_no) AS with_hierarchy
+
+ FROM (
+ SELECT oid, relname, relnamespace, relkind, relowner, (aclexplode(coalesce(relacl, acldefault('r', relowner)))).* FROM pg_class
+ ) AS c (oid, relname, relnamespace, relkind, relowner, grantor, grantee, prtype, grantable),
+ pg_namespace nc,
+ pg_authid u_grantor,
+ (
+ SELECT oid, rolname FROM pg_authid
+ UNION ALL
+ SELECT 0::oid, 'PUBLIC'
+ ) AS grantee (oid, rolname)
+
+ WHERE c.relnamespace = nc.oid
+ AND c.relkind IN ('r', 'v', 'f', 'p')
+ AND c.grantee = grantee.oid
+ AND c.grantor = u_grantor.oid
+ AND c.prtype IN ('INSERT', 'SELECT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER')
+ AND (pg_has_role(u_grantor.oid, 'USAGE')
+ OR pg_has_role(grantee.oid, 'USAGE')
+ OR grantee.rolname = 'PUBLIC');
+
+GRANT SELECT ON table_privileges TO PUBLIC;
+
+
+/*
+ * 5.43
+ * ROLE_TABLE_GRANTS view
+ */
+
+CREATE VIEW role_table_grants AS
+ SELECT grantor,
+ grantee,
+ table_catalog,
+ table_schema,
+ table_name,
+ privilege_type,
+ is_grantable,
+ with_hierarchy
+ FROM table_privileges
+ WHERE grantor IN (SELECT role_name FROM enabled_roles)
+ OR grantee IN (SELECT role_name FROM enabled_roles);
+
+GRANT SELECT ON role_table_grants TO PUBLIC;
+
+
+/*
+ * 5.63
+ * TABLES view
+ */
+
+CREATE VIEW tables AS
+ SELECT CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nc.nspname AS sql_identifier) AS table_schema,
+ CAST(c.relname AS sql_identifier) AS table_name,
+
+ CAST(
+ CASE WHEN nc.oid = pg_my_temp_schema() THEN 'LOCAL TEMPORARY'
+ WHEN c.relkind IN ('r', 'p') THEN 'BASE TABLE'
+ WHEN c.relkind = 'v' THEN 'VIEW'
+ WHEN c.relkind = 'f' THEN 'FOREIGN'
+ ELSE null END
+ AS character_data) AS table_type,
+
+ CAST(null AS sql_identifier) AS self_referencing_column_name,
+ CAST(null AS character_data) AS reference_generation,
+
+ CAST(CASE WHEN t.typname IS NOT NULL THEN current_database() ELSE null END AS sql_identifier) AS user_defined_type_catalog,
+ CAST(nt.nspname AS sql_identifier) AS user_defined_type_schema,
+ CAST(t.typname AS sql_identifier) AS user_defined_type_name,
+
+ CAST(CASE WHEN c.relkind IN ('r', 'p') OR
+ (c.relkind IN ('v', 'f') AND
+ -- 1 << CMD_INSERT
+ pg_relation_is_updatable(c.oid, false) & 8 = 8)
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_insertable_into,
+
+ CAST(CASE WHEN t.typname IS NOT NULL THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_typed,
+ CAST(null AS character_data) AS commit_action
+
+ FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace)
+ LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid)
+
+ WHERE c.relkind IN ('r', 'v', 'f', 'p')
+ AND (NOT pg_is_other_temp_schema(nc.oid))
+ AND (pg_has_role(c.relowner, 'USAGE')
+ OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') );
+
+GRANT SELECT ON tables TO PUBLIC;
+
+
+/*
+ * 5.65
+ * TRANSFORMS view
+ */
+
+CREATE VIEW transforms AS
+ SELECT CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(nt.nspname AS sql_identifier) AS udt_schema,
+ CAST(t.typname AS sql_identifier) AS udt_name,
+ CAST(current_database() AS sql_identifier) AS specific_catalog,
+ CAST(np.nspname AS sql_identifier) AS specific_schema,
+ CAST(nameconcatoid(p.proname, p.oid) AS sql_identifier) AS specific_name,
+ CAST(l.lanname AS sql_identifier) AS group_name,
+ CAST('FROM SQL' AS character_data) AS transform_type
+ FROM pg_type t JOIN pg_transform x ON t.oid = x.trftype
+ JOIN pg_language l ON x.trflang = l.oid
+ JOIN pg_proc p ON x.trffromsql = p.oid
+ JOIN pg_namespace nt ON t.typnamespace = nt.oid
+ JOIN pg_namespace np ON p.pronamespace = np.oid
+
+ UNION
+
+ SELECT CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(nt.nspname AS sql_identifier) AS udt_schema,
+ CAST(t.typname AS sql_identifier) AS udt_name,
+ CAST(current_database() AS sql_identifier) AS specific_catalog,
+ CAST(np.nspname AS sql_identifier) AS specific_schema,
+ CAST(nameconcatoid(p.proname, p.oid) AS sql_identifier) AS specific_name,
+ CAST(l.lanname AS sql_identifier) AS group_name,
+ CAST('TO SQL' AS character_data) AS transform_type
+ FROM pg_type t JOIN pg_transform x ON t.oid = x.trftype
+ JOIN pg_language l ON x.trflang = l.oid
+ JOIN pg_proc p ON x.trftosql = p.oid
+ JOIN pg_namespace nt ON t.typnamespace = nt.oid
+ JOIN pg_namespace np ON p.pronamespace = np.oid
+
+ ORDER BY udt_catalog, udt_schema, udt_name, group_name, transform_type -- some sensible grouping for interactive use
+;
+
+
+/*
+ * 5.66
+ * TRANSLATIONS view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.67
+ * TRIGGERED_UPDATE_COLUMNS view
+ */
+
+CREATE VIEW triggered_update_columns AS
+ SELECT CAST(current_database() AS sql_identifier) AS trigger_catalog,
+ CAST(n.nspname AS sql_identifier) AS trigger_schema,
+ CAST(t.tgname AS sql_identifier) AS trigger_name,
+ CAST(current_database() AS sql_identifier) AS event_object_catalog,
+ CAST(n.nspname AS sql_identifier) AS event_object_schema,
+ CAST(c.relname AS sql_identifier) AS event_object_table,
+ CAST(a.attname AS sql_identifier) AS event_object_column
+
+ FROM pg_namespace n, pg_class c, pg_trigger t,
+ (SELECT tgoid, (ta0.tgat).x AS tgattnum, (ta0.tgat).n AS tgattpos
+ FROM (SELECT oid AS tgoid, information_schema._pg_expandarray(tgattr) AS tgat FROM pg_trigger) AS ta0) AS ta,
+ pg_attribute a
+
+ WHERE n.oid = c.relnamespace
+ AND c.oid = t.tgrelid
+ AND t.oid = ta.tgoid
+ AND (a.attrelid, a.attnum) = (t.tgrelid, ta.tgattnum)
+ AND NOT t.tgisinternal
+ AND (NOT pg_is_other_temp_schema(n.oid))
+ AND (pg_has_role(c.relowner, 'USAGE')
+ -- SELECT privilege omitted, per SQL standard
+ OR has_column_privilege(c.oid, a.attnum, 'INSERT, UPDATE, REFERENCES') );
+
+GRANT SELECT ON triggered_update_columns TO PUBLIC;
+
+
+/*
+ * 5.68
+ * TRIGGER_COLUMN_USAGE view
+ */
+
+-- not tracked by PostgreSQL
+
+
+/*
+ * 5.69
+ * TRIGGER_PERIOD_USAGE view
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.70
+ * TRIGGER_ROUTINE_USAGE view
+ */
+
+-- not tracked by PostgreSQL
+
+
+/*
+ * 5.71
+ * TRIGGER_SEQUENCE_USAGE view
+ */
+
+-- not tracked by PostgreSQL
+
+
+/*
+ * 5.72
+ * TRIGGER_TABLE_USAGE view
+ */
+
+-- not tracked by PostgreSQL
+
+
+/*
+ * 5.73
+ * TRIGGERS view
+ */
+
+CREATE VIEW triggers AS
+ SELECT CAST(current_database() AS sql_identifier) AS trigger_catalog,
+ CAST(n.nspname AS sql_identifier) AS trigger_schema,
+ CAST(t.tgname AS sql_identifier) AS trigger_name,
+ CAST(em.text AS character_data) AS event_manipulation,
+ CAST(current_database() AS sql_identifier) AS event_object_catalog,
+ CAST(n.nspname AS sql_identifier) AS event_object_schema,
+ CAST(c.relname AS sql_identifier) AS event_object_table,
+ CAST(
+ -- To determine action order, partition by schema, table,
+ -- event_manipulation (INSERT/DELETE/UPDATE), ROW/STATEMENT (1),
+ -- BEFORE/AFTER (66), then order by trigger name. It's preferable
+ -- to partition by view output columns, so that query constraints
+ -- can be pushed down below the window function.
+ rank() OVER (PARTITION BY CAST(n.nspname AS sql_identifier),
+ CAST(c.relname AS sql_identifier),
+ em.num,
+ t.tgtype & 1,
+ t.tgtype & 66
+ ORDER BY t.tgname)
+ AS cardinal_number) AS action_order,
+ CAST(
+ CASE WHEN pg_has_role(c.relowner, 'USAGE')
+ THEN (regexp_match(pg_get_triggerdef(t.oid), E'.{35,} WHEN \\((.+)\\) EXECUTE FUNCTION'))[1]
+ ELSE null END
+ AS character_data) AS action_condition,
+ CAST(
+ substring(pg_get_triggerdef(t.oid) from
+ position('EXECUTE FUNCTION' in substring(pg_get_triggerdef(t.oid) from 48)) + 47)
+ AS character_data) AS action_statement,
+ CAST(
+ -- hard-wired reference to TRIGGER_TYPE_ROW
+ CASE t.tgtype & 1 WHEN 1 THEN 'ROW' ELSE 'STATEMENT' END
+ AS character_data) AS action_orientation,
+ CAST(
+ -- hard-wired refs to TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSTEAD
+ CASE t.tgtype & 66 WHEN 2 THEN 'BEFORE' WHEN 64 THEN 'INSTEAD OF' ELSE 'AFTER' END
+ AS character_data) AS action_timing,
+ CAST(tgoldtable AS sql_identifier) AS action_reference_old_table,
+ CAST(tgnewtable AS sql_identifier) AS action_reference_new_table,
+ CAST(null AS sql_identifier) AS action_reference_old_row,
+ CAST(null AS sql_identifier) AS action_reference_new_row,
+ CAST(null AS time_stamp) AS created
+
+ FROM pg_namespace n, pg_class c, pg_trigger t,
+ -- hard-wired refs to TRIGGER_TYPE_INSERT, TRIGGER_TYPE_DELETE,
+ -- TRIGGER_TYPE_UPDATE; we intentionally omit TRIGGER_TYPE_TRUNCATE
+ (VALUES (4, 'INSERT'),
+ (8, 'DELETE'),
+ (16, 'UPDATE')) AS em (num, text)
+
+ WHERE n.oid = c.relnamespace
+ AND c.oid = t.tgrelid
+ AND t.tgtype & em.num <> 0
+ AND NOT t.tgisinternal
+ AND (NOT pg_is_other_temp_schema(n.oid))
+ AND (pg_has_role(c.relowner, 'USAGE')
+ -- SELECT privilege omitted, per SQL standard
+ OR has_table_privilege(c.oid, 'INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(c.oid, 'INSERT, UPDATE, REFERENCES') );
+
+GRANT SELECT ON triggers TO PUBLIC;
+
+
+/*
+ * 5.74
+ * UDT_PRIVILEGES view
+ */
+
+CREATE VIEW udt_privileges AS
+ SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
+ CAST(grantee.rolname AS sql_identifier) AS grantee,
+ CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(n.nspname AS sql_identifier) AS udt_schema,
+ CAST(t.typname AS sql_identifier) AS udt_name,
+ CAST('TYPE USAGE' AS character_data) AS privilege_type, -- sic
+ CAST(
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, t.typowner, 'USAGE')
+ OR t.grantable
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_grantable
+
+ FROM (
+ SELECT oid, typname, typnamespace, typtype, typowner, (aclexplode(coalesce(typacl, acldefault('T', typowner)))).* FROM pg_type
+ ) AS t (oid, typname, typnamespace, typtype, typowner, grantor, grantee, prtype, grantable),
+ pg_namespace n,
+ pg_authid u_grantor,
+ (
+ SELECT oid, rolname FROM pg_authid
+ UNION ALL
+ SELECT 0::oid, 'PUBLIC'
+ ) AS grantee (oid, rolname)
+
+ WHERE t.typnamespace = n.oid
+ AND t.typtype = 'c'
+ AND t.grantee = grantee.oid
+ AND t.grantor = u_grantor.oid
+ AND t.prtype IN ('USAGE')
+ AND (pg_has_role(u_grantor.oid, 'USAGE')
+ OR pg_has_role(grantee.oid, 'USAGE')
+ OR grantee.rolname = 'PUBLIC');
+
+GRANT SELECT ON udt_privileges TO PUBLIC;
+
+
+/*
+ * 5.46
+ * ROLE_UDT_GRANTS view
+ */
+
+CREATE VIEW role_udt_grants AS
+ SELECT grantor,
+ grantee,
+ udt_catalog,
+ udt_schema,
+ udt_name,
+ privilege_type,
+ is_grantable
+ FROM udt_privileges
+ WHERE grantor IN (SELECT role_name FROM enabled_roles)
+ OR grantee IN (SELECT role_name FROM enabled_roles);
+
+GRANT SELECT ON role_udt_grants TO PUBLIC;
+
+
+/*
+ * 5.75
+ * USAGE_PRIVILEGES view
+ */
+
+CREATE VIEW usage_privileges AS
+
+ /* collations */
+ -- Collations have no real privileges, so we represent all collations with implicit usage privilege here.
+ SELECT CAST(u.rolname AS sql_identifier) AS grantor,
+ CAST('PUBLIC' AS sql_identifier) AS grantee,
+ CAST(current_database() AS sql_identifier) AS object_catalog,
+ CAST(n.nspname AS sql_identifier) AS object_schema,
+ CAST(c.collname AS sql_identifier) AS object_name,
+ CAST('COLLATION' AS character_data) AS object_type,
+ CAST('USAGE' AS character_data) AS privilege_type,
+ CAST('NO' AS yes_or_no) AS is_grantable
+
+ FROM pg_authid u,
+ pg_namespace n,
+ pg_collation c
+
+ WHERE u.oid = c.collowner
+ AND c.collnamespace = n.oid
+ AND collencoding IN (-1, (SELECT encoding FROM pg_database WHERE datname = current_database()))
+
+ UNION ALL
+
+ /* domains */
+ SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
+ CAST(grantee.rolname AS sql_identifier) AS grantee,
+ CAST(current_database() AS sql_identifier) AS object_catalog,
+ CAST(n.nspname AS sql_identifier) AS object_schema,
+ CAST(t.typname AS sql_identifier) AS object_name,
+ CAST('DOMAIN' AS character_data) AS object_type,
+ CAST('USAGE' AS character_data) AS privilege_type,
+ CAST(
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, t.typowner, 'USAGE')
+ OR t.grantable
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_grantable
+
+ FROM (
+ SELECT oid, typname, typnamespace, typtype, typowner, (aclexplode(coalesce(typacl, acldefault('T', typowner)))).* FROM pg_type
+ ) AS t (oid, typname, typnamespace, typtype, typowner, grantor, grantee, prtype, grantable),
+ pg_namespace n,
+ pg_authid u_grantor,
+ (
+ SELECT oid, rolname FROM pg_authid
+ UNION ALL
+ SELECT 0::oid, 'PUBLIC'
+ ) AS grantee (oid, rolname)
+
+ WHERE t.typnamespace = n.oid
+ AND t.typtype = 'd'
+ AND t.grantee = grantee.oid
+ AND t.grantor = u_grantor.oid
+ AND t.prtype IN ('USAGE')
+ AND (pg_has_role(u_grantor.oid, 'USAGE')
+ OR pg_has_role(grantee.oid, 'USAGE')
+ OR grantee.rolname = 'PUBLIC')
+
+ UNION ALL
+
+ /* foreign-data wrappers */
+ SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
+ CAST(grantee.rolname AS sql_identifier) AS grantee,
+ CAST(current_database() AS sql_identifier) AS object_catalog,
+ CAST('' AS sql_identifier) AS object_schema,
+ CAST(fdw.fdwname AS sql_identifier) AS object_name,
+ CAST('FOREIGN DATA WRAPPER' AS character_data) AS object_type,
+ CAST('USAGE' AS character_data) AS privilege_type,
+ CAST(
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, fdw.fdwowner, 'USAGE')
+ OR fdw.grantable
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_grantable
+
+ FROM (
+ SELECT fdwname, fdwowner, (aclexplode(coalesce(fdwacl, acldefault('F', fdwowner)))).* FROM pg_foreign_data_wrapper
+ ) AS fdw (fdwname, fdwowner, grantor, grantee, prtype, grantable),
+ pg_authid u_grantor,
+ (
+ SELECT oid, rolname FROM pg_authid
+ UNION ALL
+ SELECT 0::oid, 'PUBLIC'
+ ) AS grantee (oid, rolname)
+
+ WHERE u_grantor.oid = fdw.grantor
+ AND grantee.oid = fdw.grantee
+ AND fdw.prtype IN ('USAGE')
+ AND (pg_has_role(u_grantor.oid, 'USAGE')
+ OR pg_has_role(grantee.oid, 'USAGE')
+ OR grantee.rolname = 'PUBLIC')
+
+ UNION ALL
+
+ /* foreign servers */
+ SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
+ CAST(grantee.rolname AS sql_identifier) AS grantee,
+ CAST(current_database() AS sql_identifier) AS object_catalog,
+ CAST('' AS sql_identifier) AS object_schema,
+ CAST(srv.srvname AS sql_identifier) AS object_name,
+ CAST('FOREIGN SERVER' AS character_data) AS object_type,
+ CAST('USAGE' AS character_data) AS privilege_type,
+ CAST(
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, srv.srvowner, 'USAGE')
+ OR srv.grantable
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_grantable
+
+ FROM (
+ SELECT srvname, srvowner, (aclexplode(coalesce(srvacl, acldefault('S', srvowner)))).* FROM pg_foreign_server
+ ) AS srv (srvname, srvowner, grantor, grantee, prtype, grantable),
+ pg_authid u_grantor,
+ (
+ SELECT oid, rolname FROM pg_authid
+ UNION ALL
+ SELECT 0::oid, 'PUBLIC'
+ ) AS grantee (oid, rolname)
+
+ WHERE u_grantor.oid = srv.grantor
+ AND grantee.oid = srv.grantee
+ AND srv.prtype IN ('USAGE')
+ AND (pg_has_role(u_grantor.oid, 'USAGE')
+ OR pg_has_role(grantee.oid, 'USAGE')
+ OR grantee.rolname = 'PUBLIC')
+
+ UNION ALL
+
+ /* sequences */
+ SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
+ CAST(grantee.rolname AS sql_identifier) AS grantee,
+ CAST(current_database() AS sql_identifier) AS object_catalog,
+ CAST(n.nspname AS sql_identifier) AS object_schema,
+ CAST(c.relname AS sql_identifier) AS object_name,
+ CAST('SEQUENCE' AS character_data) AS object_type,
+ CAST('USAGE' AS character_data) AS privilege_type,
+ CAST(
+ CASE WHEN
+ -- object owner always has grant options
+ pg_has_role(grantee.oid, c.relowner, 'USAGE')
+ OR c.grantable
+ THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_grantable
+
+ FROM (
+ SELECT oid, relname, relnamespace, relkind, relowner, (aclexplode(coalesce(relacl, acldefault('r', relowner)))).* FROM pg_class
+ ) AS c (oid, relname, relnamespace, relkind, relowner, grantor, grantee, prtype, grantable),
+ pg_namespace n,
+ pg_authid u_grantor,
+ (
+ SELECT oid, rolname FROM pg_authid
+ UNION ALL
+ SELECT 0::oid, 'PUBLIC'
+ ) AS grantee (oid, rolname)
+
+ WHERE c.relnamespace = n.oid
+ AND c.relkind = 'S'
+ AND c.grantee = grantee.oid
+ AND c.grantor = u_grantor.oid
+ AND c.prtype IN ('USAGE')
+ AND (pg_has_role(u_grantor.oid, 'USAGE')
+ OR pg_has_role(grantee.oid, 'USAGE')
+ OR grantee.rolname = 'PUBLIC');
+
+GRANT SELECT ON usage_privileges TO PUBLIC;
+
+
+/*
+ * 5.45
+ * ROLE_USAGE_GRANTS view
+ */
+
+CREATE VIEW role_usage_grants AS
+ SELECT grantor,
+ grantee,
+ object_catalog,
+ object_schema,
+ object_name,
+ object_type,
+ privilege_type,
+ is_grantable
+ FROM usage_privileges
+ WHERE grantor IN (SELECT role_name FROM enabled_roles)
+ OR grantee IN (SELECT role_name FROM enabled_roles);
+
+GRANT SELECT ON role_usage_grants TO PUBLIC;
+
+
+/*
+ * 5.76
+ * USER_DEFINED_TYPES view
+ */
+
+CREATE VIEW user_defined_types AS
+ SELECT CAST(current_database() AS sql_identifier) AS user_defined_type_catalog,
+ CAST(n.nspname AS sql_identifier) AS user_defined_type_schema,
+ CAST(c.relname AS sql_identifier) AS user_defined_type_name,
+ CAST('STRUCTURED' AS character_data) AS user_defined_type_category,
+ CAST('YES' AS yes_or_no) AS is_instantiable,
+ CAST(null AS yes_or_no) AS is_final,
+ CAST(null AS character_data) AS ordering_form,
+ CAST(null AS character_data) AS ordering_category,
+ CAST(null AS sql_identifier) AS ordering_routine_catalog,
+ CAST(null AS sql_identifier) AS ordering_routine_schema,
+ CAST(null AS sql_identifier) AS ordering_routine_name,
+ CAST(null AS character_data) AS reference_type,
+ CAST(null AS character_data) AS data_type,
+ CAST(null AS cardinal_number) AS character_maximum_length,
+ CAST(null AS cardinal_number) AS character_octet_length,
+ CAST(null AS sql_identifier) AS character_set_catalog,
+ CAST(null AS sql_identifier) AS character_set_schema,
+ CAST(null AS sql_identifier) AS character_set_name,
+ CAST(null AS sql_identifier) AS collation_catalog,
+ CAST(null AS sql_identifier) AS collation_schema,
+ CAST(null AS sql_identifier) AS collation_name,
+ CAST(null AS cardinal_number) AS numeric_precision,
+ CAST(null AS cardinal_number) AS numeric_precision_radix,
+ CAST(null AS cardinal_number) AS numeric_scale,
+ CAST(null AS cardinal_number) AS datetime_precision,
+ CAST(null AS character_data) AS interval_type,
+ CAST(null AS cardinal_number) AS interval_precision,
+ CAST(null AS sql_identifier) AS source_dtd_identifier,
+ CAST(null AS sql_identifier) AS ref_dtd_identifier
+
+ FROM pg_namespace n, pg_class c, pg_type t
+
+ WHERE n.oid = c.relnamespace
+ AND t.typrelid = c.oid
+ AND c.relkind = 'c'
+ AND (pg_has_role(t.typowner, 'USAGE')
+ OR has_type_privilege(t.oid, 'USAGE'));
+
+GRANT SELECT ON user_defined_types TO PUBLIC;
+
+
+/*
+ * 5.77
+ * VIEW_COLUMN_USAGE
+ */
+
+CREATE VIEW view_column_usage AS
+ SELECT DISTINCT
+ CAST(current_database() AS sql_identifier) AS view_catalog,
+ CAST(nv.nspname AS sql_identifier) AS view_schema,
+ CAST(v.relname AS sql_identifier) AS view_name,
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nt.nspname AS sql_identifier) AS table_schema,
+ CAST(t.relname AS sql_identifier) AS table_name,
+ CAST(a.attname AS sql_identifier) AS column_name
+
+ FROM pg_namespace nv, pg_class v, pg_depend dv,
+ pg_depend dt, pg_class t, pg_namespace nt,
+ pg_attribute a
+
+ WHERE nv.oid = v.relnamespace
+ AND v.relkind = 'v'
+ AND v.oid = dv.refobjid
+ AND dv.refclassid = 'pg_catalog.pg_class'::regclass
+ AND dv.classid = 'pg_catalog.pg_rewrite'::regclass
+ AND dv.deptype = 'i'
+ AND dv.objid = dt.objid
+ AND dv.refobjid <> dt.refobjid
+ AND dt.classid = 'pg_catalog.pg_rewrite'::regclass
+ AND dt.refclassid = 'pg_catalog.pg_class'::regclass
+ AND dt.refobjid = t.oid
+ AND t.relnamespace = nt.oid
+ AND t.relkind IN ('r', 'v', 'f', 'p')
+ AND t.oid = a.attrelid
+ AND dt.refobjsubid = a.attnum
+ AND pg_has_role(t.relowner, 'USAGE');
+
+GRANT SELECT ON view_column_usage TO PUBLIC;
+
+
+/*
+ * 5.78
+ * VIEW_PERIOD_USAGE
+ */
+
+-- feature not supported
+
+
+/*
+ * 5.79
+ * VIEW_ROUTINE_USAGE
+ */
+
+CREATE VIEW view_routine_usage AS
+ SELECT DISTINCT
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nv.nspname AS sql_identifier) AS table_schema,
+ CAST(v.relname AS sql_identifier) AS table_name,
+ CAST(current_database() AS sql_identifier) AS specific_catalog,
+ CAST(np.nspname AS sql_identifier) AS specific_schema,
+ CAST(nameconcatoid(p.proname, p.oid) AS sql_identifier) AS specific_name
+
+ FROM pg_namespace nv, pg_class v, pg_depend dv,
+ pg_depend dp, pg_proc p, pg_namespace np
+
+ WHERE nv.oid = v.relnamespace
+ AND v.relkind = 'v'
+ AND v.oid = dv.refobjid
+ AND dv.refclassid = 'pg_catalog.pg_class'::regclass
+ AND dv.classid = 'pg_catalog.pg_rewrite'::regclass
+ AND dv.deptype = 'i'
+ AND dv.objid = dp.objid
+ AND dp.classid = 'pg_catalog.pg_rewrite'::regclass
+ AND dp.refclassid = 'pg_catalog.pg_proc'::regclass
+ AND dp.refobjid = p.oid
+ AND p.pronamespace = np.oid
+ AND pg_has_role(p.proowner, 'USAGE');
+
+GRANT SELECT ON view_routine_usage TO PUBLIC;
+
+
+/*
+ * 5.80
+ * VIEW_TABLE_USAGE
+ */
+
+CREATE VIEW view_table_usage AS
+ SELECT DISTINCT
+ CAST(current_database() AS sql_identifier) AS view_catalog,
+ CAST(nv.nspname AS sql_identifier) AS view_schema,
+ CAST(v.relname AS sql_identifier) AS view_name,
+ CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nt.nspname AS sql_identifier) AS table_schema,
+ CAST(t.relname AS sql_identifier) AS table_name
+
+ FROM pg_namespace nv, pg_class v, pg_depend dv,
+ pg_depend dt, pg_class t, pg_namespace nt
+
+ WHERE nv.oid = v.relnamespace
+ AND v.relkind = 'v'
+ AND v.oid = dv.refobjid
+ AND dv.refclassid = 'pg_catalog.pg_class'::regclass
+ AND dv.classid = 'pg_catalog.pg_rewrite'::regclass
+ AND dv.deptype = 'i'
+ AND dv.objid = dt.objid
+ AND dv.refobjid <> dt.refobjid
+ AND dt.classid = 'pg_catalog.pg_rewrite'::regclass
+ AND dt.refclassid = 'pg_catalog.pg_class'::regclass
+ AND dt.refobjid = t.oid
+ AND t.relnamespace = nt.oid
+ AND t.relkind IN ('r', 'v', 'f', 'p')
+ AND pg_has_role(t.relowner, 'USAGE');
+
+GRANT SELECT ON view_table_usage TO PUBLIC;
+
+
+/*
+ * 5.81
+ * VIEWS view
+ */
+
+CREATE VIEW views AS
+ SELECT CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(nc.nspname AS sql_identifier) AS table_schema,
+ CAST(c.relname AS sql_identifier) AS table_name,
+
+ CAST(
+ CASE WHEN pg_has_role(c.relowner, 'USAGE')
+ THEN pg_get_viewdef(c.oid)
+ ELSE null END
+ AS character_data) AS view_definition,
+
+ CAST(
+ CASE WHEN 'check_option=cascaded' = ANY (c.reloptions)
+ THEN 'CASCADED'
+ WHEN 'check_option=local' = ANY (c.reloptions)
+ THEN 'LOCAL'
+ ELSE 'NONE' END
+ AS character_data) AS check_option,
+
+ CAST(
+ -- (1 << CMD_UPDATE) + (1 << CMD_DELETE)
+ CASE WHEN pg_relation_is_updatable(c.oid, false) & 20 = 20
+ THEN 'YES' ELSE 'NO' END
+ AS yes_or_no) AS is_updatable,
+
+ CAST(
+ -- 1 << CMD_INSERT
+ CASE WHEN pg_relation_is_updatable(c.oid, false) & 8 = 8
+ THEN 'YES' ELSE 'NO' END
+ AS yes_or_no) AS is_insertable_into,
+
+ CAST(
+ -- TRIGGER_TYPE_ROW + TRIGGER_TYPE_INSTEAD + TRIGGER_TYPE_UPDATE
+ CASE WHEN EXISTS (SELECT 1 FROM pg_trigger WHERE tgrelid = c.oid AND tgtype & 81 = 81)
+ THEN 'YES' ELSE 'NO' END
+ AS yes_or_no) AS is_trigger_updatable,
+
+ CAST(
+ -- TRIGGER_TYPE_ROW + TRIGGER_TYPE_INSTEAD + TRIGGER_TYPE_DELETE
+ CASE WHEN EXISTS (SELECT 1 FROM pg_trigger WHERE tgrelid = c.oid AND tgtype & 73 = 73)
+ THEN 'YES' ELSE 'NO' END
+ AS yes_or_no) AS is_trigger_deletable,
+
+ CAST(
+ -- TRIGGER_TYPE_ROW + TRIGGER_TYPE_INSTEAD + TRIGGER_TYPE_INSERT
+ CASE WHEN EXISTS (SELECT 1 FROM pg_trigger WHERE tgrelid = c.oid AND tgtype & 69 = 69)
+ THEN 'YES' ELSE 'NO' END
+ AS yes_or_no) AS is_trigger_insertable_into
+
+ FROM pg_namespace nc, pg_class c
+
+ WHERE c.relnamespace = nc.oid
+ AND c.relkind = 'v'
+ AND (NOT pg_is_other_temp_schema(nc.oid))
+ AND (pg_has_role(c.relowner, 'USAGE')
+ OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') );
+
+GRANT SELECT ON views TO PUBLIC;
+
+
+-- The following views have dependencies that force them to appear out of order.
+
+/*
+ * 5.25
+ * DATA_TYPE_PRIVILEGES view
+ */
+
+CREATE VIEW data_type_privileges AS
+ SELECT CAST(current_database() AS sql_identifier) AS object_catalog,
+ CAST(x.objschema AS sql_identifier) AS object_schema,
+ CAST(x.objname AS sql_identifier) AS object_name,
+ CAST(x.objtype AS character_data) AS object_type,
+ CAST(x.objdtdid AS sql_identifier) AS dtd_identifier
+
+ FROM
+ (
+ SELECT udt_schema, udt_name, 'USER-DEFINED TYPE'::text, dtd_identifier FROM attributes
+ UNION ALL
+ SELECT table_schema, table_name, 'TABLE'::text, dtd_identifier FROM columns
+ UNION ALL
+ SELECT domain_schema, domain_name, 'DOMAIN'::text, dtd_identifier FROM domains
+ UNION ALL
+ SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM parameters
+ UNION ALL
+ SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM routines
+ ) AS x (objschema, objname, objtype, objdtdid);
+
+GRANT SELECT ON data_type_privileges TO PUBLIC;
+
+
+/*
+ * 5.30
+ * ELEMENT_TYPES view
+ */
+
+CREATE VIEW element_types AS
+ SELECT CAST(current_database() AS sql_identifier) AS object_catalog,
+ CAST(n.nspname AS sql_identifier) AS object_schema,
+ CAST(x.objname AS sql_identifier) AS object_name,
+ CAST(x.objtype AS character_data) AS object_type,
+ CAST(x.objdtdid AS sql_identifier) AS collection_type_identifier,
+ CAST(
+ CASE WHEN nbt.nspname = 'pg_catalog' THEN format_type(bt.oid, null)
+ ELSE 'USER-DEFINED' END AS character_data) AS data_type,
+
+ CAST(null AS cardinal_number) AS character_maximum_length,
+ CAST(null AS cardinal_number) AS character_octet_length,
+ CAST(null AS sql_identifier) AS character_set_catalog,
+ CAST(null AS sql_identifier) AS character_set_schema,
+ CAST(null AS sql_identifier) AS character_set_name,
+ CAST(CASE WHEN nco.nspname IS NOT NULL THEN current_database() END AS sql_identifier) AS collation_catalog,
+ CAST(nco.nspname AS sql_identifier) AS collation_schema,
+ CAST(co.collname AS sql_identifier) AS collation_name,
+ CAST(null AS cardinal_number) AS numeric_precision,
+ CAST(null AS cardinal_number) AS numeric_precision_radix,
+ CAST(null AS cardinal_number) AS numeric_scale,
+ CAST(null AS cardinal_number) AS datetime_precision,
+ CAST(null AS character_data) AS interval_type,
+ CAST(null AS cardinal_number) AS interval_precision,
+
+ CAST(null AS character_data) AS domain_default, -- XXX maybe a bug in the standard
+
+ CAST(current_database() AS sql_identifier) AS udt_catalog,
+ CAST(nbt.nspname AS sql_identifier) AS udt_schema,
+ CAST(bt.typname AS sql_identifier) AS udt_name,
+
+ CAST(null AS sql_identifier) AS scope_catalog,
+ CAST(null AS sql_identifier) AS scope_schema,
+ CAST(null AS sql_identifier) AS scope_name,
+
+ CAST(null AS cardinal_number) AS maximum_cardinality,
+ CAST('a' || CAST(x.objdtdid AS text) AS sql_identifier) AS dtd_identifier
+
+ FROM pg_namespace n, pg_type at, pg_namespace nbt, pg_type bt,
+ (
+ /* columns, attributes */
+ SELECT c.relnamespace, CAST(c.relname AS sql_identifier),
+ CASE WHEN c.relkind = 'c' THEN 'USER-DEFINED TYPE'::text ELSE 'TABLE'::text END,
+ a.attnum, a.atttypid, a.attcollation
+ FROM pg_class c, pg_attribute a
+ WHERE c.oid = a.attrelid
+ AND c.relkind IN ('r', 'v', 'f', 'c', 'p')
+ AND attnum > 0 AND NOT attisdropped
+
+ UNION ALL
+
+ /* domains */
+ SELECT t.typnamespace, CAST(t.typname AS sql_identifier),
+ 'DOMAIN'::text, 1, t.typbasetype, t.typcollation
+ FROM pg_type t
+ WHERE t.typtype = 'd'
+
+ UNION ALL
+
+ /* parameters */
+ SELECT pronamespace,
+ CAST(nameconcatoid(proname, oid) AS sql_identifier),
+ 'ROUTINE'::text, (ss.x).n, (ss.x).x, 0
+ FROM (SELECT p.pronamespace, p.proname, p.oid,
+ _pg_expandarray(coalesce(p.proallargtypes, p.proargtypes::oid[])) AS x
+ FROM pg_proc p) AS ss
+
+ UNION ALL
+
+ /* result types */
+ SELECT p.pronamespace,
+ CAST(nameconcatoid(p.proname, p.oid) AS sql_identifier),
+ 'ROUTINE'::text, 0, p.prorettype, 0
+ FROM pg_proc p
+
+ ) AS x (objschema, objname, objtype, objdtdid, objtypeid, objcollation)
+ LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid))
+ ON x.objcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default')
+
+ WHERE n.oid = x.objschema
+ AND at.oid = x.objtypeid
+ AND (at.typelem <> 0 AND at.typlen = -1)
+ AND at.typelem = bt.oid
+ AND nbt.oid = bt.typnamespace
+
+ AND (n.nspname, x.objname, x.objtype, CAST(x.objdtdid AS sql_identifier)) IN
+ ( SELECT object_schema, object_name, object_type, dtd_identifier
+ FROM data_type_privileges );
+
+GRANT SELECT ON element_types TO PUBLIC;
+
+
+-- SQL/MED views; these use section numbers from part 9 of the standard.
+
+/* Base view for foreign table columns */
+CREATE VIEW _pg_foreign_table_columns AS
+ SELECT n.nspname,
+ c.relname,
+ a.attname,
+ a.attfdwoptions
+ FROM pg_foreign_table t, pg_authid u, pg_namespace n, pg_class c,
+ pg_attribute a
+ WHERE u.oid = c.relowner
+ AND (pg_has_role(c.relowner, 'USAGE')
+ OR has_column_privilege(c.oid, a.attnum, 'SELECT, INSERT, UPDATE, REFERENCES'))
+ AND n.oid = c.relnamespace
+ AND c.oid = t.ftrelid
+ AND c.relkind = 'f'
+ AND a.attrelid = c.oid
+ AND a.attnum > 0;
+
+/*
+ * 24.2
+ * COLUMN_OPTIONS view
+ */
+CREATE VIEW column_options AS
+ SELECT CAST(current_database() AS sql_identifier) AS table_catalog,
+ CAST(c.nspname AS sql_identifier) AS table_schema,
+ CAST(c.relname AS sql_identifier) AS table_name,
+ CAST(c.attname AS sql_identifier) AS column_name,
+ CAST((pg_options_to_table(c.attfdwoptions)).option_name AS sql_identifier) AS option_name,
+ CAST((pg_options_to_table(c.attfdwoptions)).option_value AS character_data) AS option_value
+ FROM _pg_foreign_table_columns c;
+
+GRANT SELECT ON column_options TO PUBLIC;
+
+
+/* Base view for foreign-data wrappers */
+CREATE VIEW _pg_foreign_data_wrappers AS
+ SELECT w.oid,
+ w.fdwowner,
+ w.fdwoptions,
+ CAST(current_database() AS sql_identifier) AS foreign_data_wrapper_catalog,
+ CAST(fdwname AS sql_identifier) AS foreign_data_wrapper_name,
+ CAST(u.rolname AS sql_identifier) AS authorization_identifier,
+ CAST('c' AS character_data) AS foreign_data_wrapper_language
+ FROM pg_foreign_data_wrapper w, pg_authid u
+ WHERE u.oid = w.fdwowner
+ AND (pg_has_role(fdwowner, 'USAGE')
+ OR has_foreign_data_wrapper_privilege(w.oid, 'USAGE'));
+
+
+/*
+ * 24.4
+ * FOREIGN_DATA_WRAPPER_OPTIONS view
+ */
+CREATE VIEW foreign_data_wrapper_options AS
+ SELECT foreign_data_wrapper_catalog,
+ foreign_data_wrapper_name,
+ CAST((pg_options_to_table(w.fdwoptions)).option_name AS sql_identifier) AS option_name,
+ CAST((pg_options_to_table(w.fdwoptions)).option_value AS character_data) AS option_value
+ FROM _pg_foreign_data_wrappers w;
+
+GRANT SELECT ON foreign_data_wrapper_options TO PUBLIC;
+
+
+/*
+ * 24.5
+ * FOREIGN_DATA_WRAPPERS view
+ */
+CREATE VIEW foreign_data_wrappers AS
+ SELECT foreign_data_wrapper_catalog,
+ foreign_data_wrapper_name,
+ authorization_identifier,
+ CAST(NULL AS character_data) AS library_name,
+ foreign_data_wrapper_language
+ FROM _pg_foreign_data_wrappers w;
+
+GRANT SELECT ON foreign_data_wrappers TO PUBLIC;
+
+
+/* Base view for foreign servers */
+CREATE VIEW _pg_foreign_servers AS
+ SELECT s.oid,
+ s.srvoptions,
+ CAST(current_database() AS sql_identifier) AS foreign_server_catalog,
+ CAST(srvname AS sql_identifier) AS foreign_server_name,
+ CAST(current_database() AS sql_identifier) AS foreign_data_wrapper_catalog,
+ CAST(w.fdwname AS sql_identifier) AS foreign_data_wrapper_name,
+ CAST(srvtype AS character_data) AS foreign_server_type,
+ CAST(srvversion AS character_data) AS foreign_server_version,
+ CAST(u.rolname AS sql_identifier) AS authorization_identifier
+ FROM pg_foreign_server s, pg_foreign_data_wrapper w, pg_authid u
+ WHERE w.oid = s.srvfdw
+ AND u.oid = s.srvowner
+ AND (pg_has_role(s.srvowner, 'USAGE')
+ OR has_server_privilege(s.oid, 'USAGE'));
+
+
+/*
+ * 24.6
+ * FOREIGN_SERVER_OPTIONS view
+ */
+CREATE VIEW foreign_server_options AS
+ SELECT foreign_server_catalog,
+ foreign_server_name,
+ CAST((pg_options_to_table(s.srvoptions)).option_name AS sql_identifier) AS option_name,
+ CAST((pg_options_to_table(s.srvoptions)).option_value AS character_data) AS option_value
+ FROM _pg_foreign_servers s;
+
+GRANT SELECT ON TABLE foreign_server_options TO PUBLIC;
+
+
+/*
+ * 24.7
+ * FOREIGN_SERVERS view
+ */
+CREATE VIEW foreign_servers AS
+ SELECT foreign_server_catalog,
+ foreign_server_name,
+ foreign_data_wrapper_catalog,
+ foreign_data_wrapper_name,
+ foreign_server_type,
+ foreign_server_version,
+ authorization_identifier
+ FROM _pg_foreign_servers;
+
+GRANT SELECT ON foreign_servers TO PUBLIC;
+
+
+/* Base view for foreign tables */
+CREATE VIEW _pg_foreign_tables AS
+ SELECT
+ CAST(current_database() AS sql_identifier) AS foreign_table_catalog,
+ CAST(n.nspname AS sql_identifier) AS foreign_table_schema,
+ CAST(c.relname AS sql_identifier) AS foreign_table_name,
+ t.ftoptions AS ftoptions,
+ CAST(current_database() AS sql_identifier) AS foreign_server_catalog,
+ CAST(srvname AS sql_identifier) AS foreign_server_name,
+ CAST(u.rolname AS sql_identifier) AS authorization_identifier
+ FROM pg_foreign_table t, pg_foreign_server s, pg_foreign_data_wrapper w,
+ pg_authid u, pg_namespace n, pg_class c
+ WHERE w.oid = s.srvfdw
+ AND u.oid = c.relowner
+ AND (pg_has_role(c.relowner, 'USAGE')
+ OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER')
+ OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES'))
+ AND n.oid = c.relnamespace
+ AND c.oid = t.ftrelid
+ AND c.relkind = 'f'
+ AND s.oid = t.ftserver;
+
+
+/*
+ * 24.8
+ * FOREIGN_TABLE_OPTIONS view
+ */
+CREATE VIEW foreign_table_options AS
+ SELECT foreign_table_catalog,
+ foreign_table_schema,
+ foreign_table_name,
+ CAST((pg_options_to_table(t.ftoptions)).option_name AS sql_identifier) AS option_name,
+ CAST((pg_options_to_table(t.ftoptions)).option_value AS character_data) AS option_value
+ FROM _pg_foreign_tables t;
+
+GRANT SELECT ON TABLE foreign_table_options TO PUBLIC;
+
+
+/*
+ * 24.9
+ * FOREIGN_TABLES view
+ */
+CREATE VIEW foreign_tables AS
+ SELECT foreign_table_catalog,
+ foreign_table_schema,
+ foreign_table_name,
+ foreign_server_catalog,
+ foreign_server_name
+ FROM _pg_foreign_tables;
+
+GRANT SELECT ON foreign_tables TO PUBLIC;
+
+
+
+/* Base view for user mappings */
+CREATE VIEW _pg_user_mappings AS
+ SELECT um.oid,
+ um.umoptions,
+ um.umuser,
+ CAST(COALESCE(u.rolname,'PUBLIC') AS sql_identifier ) AS authorization_identifier,
+ s.foreign_server_catalog,
+ s.foreign_server_name,
+ s.authorization_identifier AS srvowner
+ FROM pg_user_mapping um LEFT JOIN pg_authid u ON (u.oid = um.umuser),
+ _pg_foreign_servers s
+ WHERE s.oid = um.umserver;
+
+
+/*
+ * 24.12
+ * USER_MAPPING_OPTIONS view
+ */
+CREATE VIEW user_mapping_options AS
+ SELECT authorization_identifier,
+ foreign_server_catalog,
+ foreign_server_name,
+ CAST(opts.option_name AS sql_identifier) AS option_name,
+ CAST(CASE WHEN (umuser <> 0 AND authorization_identifier = current_user)
+ OR (umuser = 0 AND pg_has_role(srvowner, 'USAGE'))
+ OR (SELECT rolsuper FROM pg_authid WHERE rolname = current_user)
+ THEN opts.option_value
+ ELSE NULL END AS character_data) AS option_value
+ FROM _pg_user_mappings um,
+ pg_options_to_table(um.umoptions) opts;
+
+GRANT SELECT ON user_mapping_options TO PUBLIC;
+
+
+/*
+ * 24.13
+ * USER_MAPPINGS view
+ */
+CREATE VIEW user_mappings AS
+ SELECT authorization_identifier,
+ foreign_server_catalog,
+ foreign_server_name
+ FROM _pg_user_mappings;
+
+GRANT SELECT ON user_mappings TO PUBLIC;
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
new file mode 100644
index 0000000..2ec2301
--- /dev/null
+++ b/src/backend/catalog/namespace.c
@@ -0,0 +1,4614 @@
+/*-------------------------------------------------------------------------
+ *
+ * namespace.c
+ * code to support accessing and searching namespaces
+ *
+ * This is separate from pg_namespace.c, which contains the routines that
+ * directly manipulate the pg_namespace system catalog. This module
+ * provides routines associated with defining a "namespace search path"
+ * and implementing search-path-controlled searches.
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/namespace.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/parallel.h"
+#include "access/xact.h"
+#include "access/xlog.h"
+#include "catalog/dependency.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_conversion.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_opfamily.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_statistic_ext.h"
+#include "catalog/pg_ts_config.h"
+#include "catalog/pg_ts_dict.h"
+#include "catalog/pg_ts_parser.h"
+#include "catalog/pg_ts_template.h"
+#include "catalog/pg_type.h"
+#include "commands/dbcommands.h"
+#include "funcapi.h"
+#include "mb/pg_wchar.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "parser/parse_func.h"
+#include "storage/ipc.h"
+#include "storage/lmgr.h"
+#include "storage/sinvaladt.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/catcache.h"
+#include "utils/guc.h"
+#include "utils/inval.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/syscache.h"
+#include "utils/varlena.h"
+
+
+/*
+ * The namespace search path is a possibly-empty list of namespace OIDs.
+ * In addition to the explicit list, implicitly-searched namespaces
+ * may be included:
+ *
+ * 1. If a TEMP table namespace has been initialized in this session, it
+ * is implicitly searched first. (The only time this doesn't happen is
+ * when we are obeying an override search path spec that says not to use the
+ * temp namespace, or the temp namespace is included in the explicit list.)
+ *
+ * 2. The system catalog namespace is always searched. If the system
+ * namespace is present in the explicit path then it will be searched in
+ * the specified order; otherwise it will be searched after TEMP tables and
+ * *before* the explicit list. (It might seem that the system namespace
+ * should be implicitly last, but this behavior appears to be required by
+ * SQL99. Also, this provides a way to search the system namespace first
+ * without thereby making it the default creation target namespace.)
+ *
+ * For security reasons, searches using the search path will ignore the temp
+ * namespace when searching for any object type other than relations and
+ * types. (We must allow types since temp tables have rowtypes.)
+ *
+ * The default creation target namespace is always the first element of the
+ * explicit list. If the explicit list is empty, there is no default target.
+ *
+ * The textual specification of search_path can include "$user" to refer to
+ * the namespace named the same as the current user, if any. (This is just
+ * ignored if there is no such namespace.) Also, it can include "pg_temp"
+ * to refer to the current backend's temp namespace. This is usually also
+ * ignorable if the temp namespace hasn't been set up, but there's a special
+ * case: if "pg_temp" appears first then it should be the default creation
+ * target. We kluge this case a little bit so that the temp namespace isn't
+ * set up until the first attempt to create something in it. (The reason for
+ * klugery is that we can't create the temp namespace outside a transaction,
+ * but initial GUC processing of search_path happens outside a transaction.)
+ * activeTempCreationPending is true if "pg_temp" appears first in the string
+ * but is not reflected in activeCreationNamespace because the namespace isn't
+ * set up yet.
+ *
+ * In bootstrap mode, the search path is set equal to "pg_catalog", so that
+ * the system namespace is the only one searched or inserted into.
+ * initdb is also careful to set search_path to "pg_catalog" for its
+ * post-bootstrap standalone backend runs. Otherwise the default search
+ * path is determined by GUC. The factory default path contains the PUBLIC
+ * namespace (if it exists), preceded by the user's personal namespace
+ * (if one exists).
+ *
+ * We support a stack of "override" search path settings for use within
+ * specific sections of backend code. namespace_search_path is ignored
+ * whenever the override stack is nonempty. activeSearchPath is always
+ * the actually active path; it points either to the search list of the
+ * topmost stack entry, or to baseSearchPath which is the list derived
+ * from namespace_search_path.
+ *
+ * If baseSearchPathValid is false, then baseSearchPath (and other
+ * derived variables) need to be recomputed from namespace_search_path.
+ * We mark it invalid upon an assignment to namespace_search_path or receipt
+ * of a syscache invalidation event for pg_namespace. The recomputation
+ * is done during the next non-overridden lookup attempt. Note that an
+ * override spec is never subject to recomputation.
+ *
+ * Any namespaces mentioned in namespace_search_path that are not readable
+ * by the current user ID are simply left out of baseSearchPath; so
+ * we have to be willing to recompute the path when current userid changes.
+ * namespaceUser is the userid the path has been computed for.
+ *
+ * Note: all data pointed to by these List variables is in TopMemoryContext.
+ *
+ * activePathGeneration is incremented whenever the effective values of
+ * activeSearchPath/activeCreationNamespace/activeTempCreationPending change.
+ * This can be used to quickly detect whether any change has happened since
+ * a previous examination of the search path state.
+ */
+
+/* These variables define the actually active state: */
+
+static List *activeSearchPath = NIL;
+
+/* default place to create stuff; if InvalidOid, no default */
+static Oid activeCreationNamespace = InvalidOid;
+
+/* if true, activeCreationNamespace is wrong, it should be temp namespace */
+static bool activeTempCreationPending = false;
+
+/* current generation counter; make sure this is never zero */
+static uint64 activePathGeneration = 1;
+
+/* These variables are the values last derived from namespace_search_path: */
+
+static List *baseSearchPath = NIL;
+
+static Oid baseCreationNamespace = InvalidOid;
+
+static bool baseTempCreationPending = false;
+
+static Oid namespaceUser = InvalidOid;
+
+/* The above four values are valid only if baseSearchPathValid */
+static bool baseSearchPathValid = true;
+
+/* Override requests are remembered in a stack of OverrideStackEntry structs */
+
+typedef struct
+{
+ List *searchPath; /* the desired search path */
+ Oid creationNamespace; /* the desired creation namespace */
+ int nestLevel; /* subtransaction nesting level */
+} OverrideStackEntry;
+
+static List *overrideStack = NIL;
+
+/*
+ * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
+ * in a particular backend session (this happens when a CREATE TEMP TABLE
+ * command is first executed). Thereafter it's the OID of the temp namespace.
+ *
+ * myTempToastNamespace is the OID of the namespace for my temp tables' toast
+ * tables. It is set when myTempNamespace is, and is InvalidOid before that.
+ *
+ * myTempNamespaceSubID shows whether we've created the TEMP namespace in the
+ * current subtransaction. The flag propagates up the subtransaction tree,
+ * so the main transaction will correctly recognize the flag if all
+ * intermediate subtransactions commit. When it is InvalidSubTransactionId,
+ * we either haven't made the TEMP namespace yet, or have successfully
+ * committed its creation, depending on whether myTempNamespace is valid.
+ */
+static Oid myTempNamespace = InvalidOid;
+
+static Oid myTempToastNamespace = InvalidOid;
+
+static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
+
+/*
+ * This is the user's textual search path specification --- it's the value
+ * of the GUC variable 'search_path'.
+ */
+char *namespace_search_path = NULL;
+
+
+/* Local functions */
+static void recomputeNamespacePath(void);
+static void AccessTempTableNamespace(bool force);
+static void InitTempTableNamespace(void);
+static void RemoveTempRelations(Oid tempNamespaceId);
+static void RemoveTempRelationsCallback(int code, Datum arg);
+static void NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue);
+static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
+ int **argnumbers);
+
+
+/*
+ * RangeVarGetRelidExtended
+ * Given a RangeVar describing an existing relation,
+ * select the proper namespace and look up the relation OID.
+ *
+ * If the schema or relation is not found, return InvalidOid if flags contains
+ * RVR_MISSING_OK, otherwise raise an error.
+ *
+ * If flags contains RVR_NOWAIT, throw an error if we'd have to wait for a
+ * lock.
+ *
+ * If flags contains RVR_SKIP_LOCKED, return InvalidOid if we'd have to wait
+ * for a lock.
+ *
+ * flags cannot contain both RVR_NOWAIT and RVR_SKIP_LOCKED.
+ *
+ * Note that if RVR_MISSING_OK and RVR_SKIP_LOCKED are both specified, a
+ * return value of InvalidOid could either mean the relation is missing or it
+ * could not be locked.
+ *
+ * Callback allows caller to check permissions or acquire additional locks
+ * prior to grabbing the relation lock.
+ */
+Oid
+RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode,
+ uint32 flags,
+ RangeVarGetRelidCallback callback, void *callback_arg)
+{
+ uint64 inval_count;
+ Oid relId;
+ Oid oldRelId = InvalidOid;
+ bool retry = false;
+ bool missing_ok = (flags & RVR_MISSING_OK) != 0;
+
+ /* verify that flags do no conflict */
+ Assert(!((flags & RVR_NOWAIT) && (flags & RVR_SKIP_LOCKED)));
+
+ /*
+ * We check the catalog name and then ignore it.
+ */
+ if (relation->catalogname)
+ {
+ if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
+ relation->catalogname, relation->schemaname,
+ relation->relname)));
+ }
+
+ /*
+ * DDL operations can change the results of a name lookup. Since all such
+ * operations will generate invalidation messages, we keep track of
+ * whether any such messages show up while we're performing the operation,
+ * and retry until either (1) no more invalidation messages show up or (2)
+ * the answer doesn't change.
+ *
+ * But if lockmode = NoLock, then we assume that either the caller is OK
+ * with the answer changing under them, or that they already hold some
+ * appropriate lock, and therefore return the first answer we get without
+ * checking for invalidation messages. Also, if the requested lock is
+ * already held, LockRelationOid will not AcceptInvalidationMessages, so
+ * we may fail to notice a change. We could protect against that case by
+ * calling AcceptInvalidationMessages() before beginning this loop, but
+ * that would add a significant amount overhead, so for now we don't.
+ */
+ for (;;)
+ {
+ /*
+ * Remember this value, so that, after looking up the relation name
+ * and locking its OID, we can check whether any invalidation messages
+ * have been processed that might require a do-over.
+ */
+ inval_count = SharedInvalidMessageCounter;
+
+ /*
+ * Some non-default relpersistence value may have been specified. The
+ * parser never generates such a RangeVar in simple DML, but it can
+ * happen in contexts such as "CREATE TEMP TABLE foo (f1 int PRIMARY
+ * KEY)". Such a command will generate an added CREATE INDEX
+ * operation, which must be careful to find the temp table, even when
+ * pg_temp is not first in the search path.
+ */
+ if (relation->relpersistence == RELPERSISTENCE_TEMP)
+ {
+ if (!OidIsValid(myTempNamespace))
+ relId = InvalidOid; /* this probably can't happen? */
+ else
+ {
+ if (relation->schemaname)
+ {
+ Oid namespaceId;
+
+ namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
+
+ /*
+ * For missing_ok, allow a non-existent schema name to
+ * return InvalidOid.
+ */
+ if (namespaceId != myTempNamespace)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("temporary tables cannot specify a schema name")));
+ }
+
+ relId = get_relname_relid(relation->relname, myTempNamespace);
+ }
+ }
+ else if (relation->schemaname)
+ {
+ Oid namespaceId;
+
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ relId = InvalidOid;
+ else
+ relId = get_relname_relid(relation->relname, namespaceId);
+ }
+ else
+ {
+ /* search the namespace path */
+ relId = RelnameGetRelid(relation->relname);
+ }
+
+ /*
+ * Invoke caller-supplied callback, if any.
+ *
+ * This callback is a good place to check permissions: we haven't
+ * taken the table lock yet (and it's really best to check permissions
+ * before locking anything!), but we've gotten far enough to know what
+ * OID we think we should lock. Of course, concurrent DDL might
+ * change things while we're waiting for the lock, but in that case
+ * the callback will be invoked again for the new OID.
+ */
+ if (callback)
+ callback(relation, relId, oldRelId, callback_arg);
+
+ /*
+ * If no lock requested, we assume the caller knows what they're
+ * doing. They should have already acquired a heavyweight lock on
+ * this relation earlier in the processing of this same statement, so
+ * it wouldn't be appropriate to AcceptInvalidationMessages() here, as
+ * that might pull the rug out from under them.
+ */
+ if (lockmode == NoLock)
+ break;
+
+ /*
+ * If, upon retry, we get back the same OID we did last time, then the
+ * invalidation messages we processed did not change the final answer.
+ * So we're done.
+ *
+ * If we got a different OID, we've locked the relation that used to
+ * have this name rather than the one that does now. So release the
+ * lock.
+ */
+ if (retry)
+ {
+ if (relId == oldRelId)
+ break;
+ if (OidIsValid(oldRelId))
+ UnlockRelationOid(oldRelId, lockmode);
+ }
+
+ /*
+ * Lock relation. This will also accept any pending invalidation
+ * messages. If we got back InvalidOid, indicating not found, then
+ * there's nothing to lock, but we accept invalidation messages
+ * anyway, to flush any negative catcache entries that may be
+ * lingering.
+ */
+ if (!OidIsValid(relId))
+ AcceptInvalidationMessages();
+ else if (!(flags & (RVR_NOWAIT | RVR_SKIP_LOCKED)))
+ LockRelationOid(relId, lockmode);
+ else if (!ConditionalLockRelationOid(relId, lockmode))
+ {
+ int elevel = (flags & RVR_SKIP_LOCKED) ? DEBUG1 : ERROR;
+
+ if (relation->schemaname)
+ ereport(elevel,
+ (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
+ errmsg("could not obtain lock on relation \"%s.%s\"",
+ relation->schemaname, relation->relname)));
+ else
+ ereport(elevel,
+ (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
+ errmsg("could not obtain lock on relation \"%s\"",
+ relation->relname)));
+
+ return InvalidOid;
+ }
+
+ /*
+ * If no invalidation message were processed, we're done!
+ */
+ if (inval_count == SharedInvalidMessageCounter)
+ break;
+
+ /*
+ * Something may have changed. Let's repeat the name lookup, to make
+ * sure this name still references the same relation it did
+ * previously.
+ */
+ retry = true;
+ oldRelId = relId;
+ }
+
+ if (!OidIsValid(relId))
+ {
+ int elevel = missing_ok ? DEBUG1 : ERROR;
+
+ if (relation->schemaname)
+ ereport(elevel,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("relation \"%s.%s\" does not exist",
+ relation->schemaname, relation->relname)));
+ else
+ ereport(elevel,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("relation \"%s\" does not exist",
+ relation->relname)));
+ }
+ return relId;
+}
+
+/*
+ * RangeVarGetCreationNamespace
+ * Given a RangeVar describing a to-be-created relation,
+ * choose which namespace to create it in.
+ *
+ * Note: calling this may result in a CommandCounterIncrement operation.
+ * That will happen on the first request for a temp table in any particular
+ * backend run; we will need to either create or clean out the temp schema.
+ */
+Oid
+RangeVarGetCreationNamespace(const RangeVar *newRelation)
+{
+ Oid namespaceId;
+
+ /*
+ * We check the catalog name and then ignore it.
+ */
+ if (newRelation->catalogname)
+ {
+ if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
+ newRelation->catalogname, newRelation->schemaname,
+ newRelation->relname)));
+ }
+
+ if (newRelation->schemaname)
+ {
+ /* check for pg_temp alias */
+ if (strcmp(newRelation->schemaname, "pg_temp") == 0)
+ {
+ /* Initialize temp namespace */
+ AccessTempTableNamespace(false);
+ return myTempNamespace;
+ }
+ /* use exact schema given */
+ namespaceId = get_namespace_oid(newRelation->schemaname, false);
+ /* we do not check for USAGE rights here! */
+ }
+ else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
+ {
+ /* Initialize temp namespace */
+ AccessTempTableNamespace(false);
+ return myTempNamespace;
+ }
+ else
+ {
+ /* use the default creation namespace */
+ recomputeNamespacePath();
+ if (activeTempCreationPending)
+ {
+ /* Need to initialize temp namespace */
+ AccessTempTableNamespace(true);
+ return myTempNamespace;
+ }
+ namespaceId = activeCreationNamespace;
+ if (!OidIsValid(namespaceId))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_SCHEMA),
+ errmsg("no schema has been selected to create in")));
+ }
+
+ /* Note: callers will check for CREATE rights when appropriate */
+
+ return namespaceId;
+}
+
+/*
+ * RangeVarGetAndCheckCreationNamespace
+ *
+ * This function returns the OID of the namespace in which a new relation
+ * with a given name should be created. If the user does not have CREATE
+ * permission on the target namespace, this function will instead signal
+ * an ERROR.
+ *
+ * If non-NULL, *existing_relation_id is set to the OID of any existing relation
+ * with the same name which already exists in that namespace, or to InvalidOid
+ * if no such relation exists.
+ *
+ * If lockmode != NoLock, the specified lock mode is acquired on the existing
+ * relation, if any, provided that the current user owns the target relation.
+ * However, if lockmode != NoLock and the user does not own the target
+ * relation, we throw an ERROR, as we must not try to lock relations the
+ * user does not have permissions on.
+ *
+ * As a side effect, this function acquires AccessShareLock on the target
+ * namespace. Without this, the namespace could be dropped before our
+ * transaction commits, leaving behind relations with relnamespace pointing
+ * to a no-longer-existent namespace.
+ *
+ * As a further side-effect, if the selected namespace is a temporary namespace,
+ * we mark the RangeVar as RELPERSISTENCE_TEMP.
+ */
+Oid
+RangeVarGetAndCheckCreationNamespace(RangeVar *relation,
+ LOCKMODE lockmode,
+ Oid *existing_relation_id)
+{
+ uint64 inval_count;
+ Oid relid;
+ Oid oldrelid = InvalidOid;
+ Oid nspid;
+ Oid oldnspid = InvalidOid;
+ bool retry = false;
+
+ /*
+ * We check the catalog name and then ignore it.
+ */
+ if (relation->catalogname)
+ {
+ if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
+ relation->catalogname, relation->schemaname,
+ relation->relname)));
+ }
+
+ /*
+ * As in RangeVarGetRelidExtended(), we guard against concurrent DDL
+ * operations by tracking whether any invalidation messages are processed
+ * while we're doing the name lookups and acquiring locks. See comments
+ * in that function for a more detailed explanation of this logic.
+ */
+ for (;;)
+ {
+ AclResult aclresult;
+
+ inval_count = SharedInvalidMessageCounter;
+
+ /* Look up creation namespace and check for existing relation. */
+ nspid = RangeVarGetCreationNamespace(relation);
+ Assert(OidIsValid(nspid));
+ if (existing_relation_id != NULL)
+ relid = get_relname_relid(relation->relname, nspid);
+ else
+ relid = InvalidOid;
+
+ /*
+ * In bootstrap processing mode, we don't bother with permissions or
+ * locking. Permissions might not be working yet, and locking is
+ * unnecessary.
+ */
+ if (IsBootstrapProcessingMode())
+ break;
+
+ /* Check namespace permissions. */
+ aclresult = pg_namespace_aclcheck(nspid, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, OBJECT_SCHEMA,
+ get_namespace_name(nspid));
+
+ if (retry)
+ {
+ /* If nothing changed, we're done. */
+ if (relid == oldrelid && nspid == oldnspid)
+ break;
+ /* If creation namespace has changed, give up old lock. */
+ if (nspid != oldnspid)
+ UnlockDatabaseObject(NamespaceRelationId, oldnspid, 0,
+ AccessShareLock);
+ /* If name points to something different, give up old lock. */
+ if (relid != oldrelid && OidIsValid(oldrelid) && lockmode != NoLock)
+ UnlockRelationOid(oldrelid, lockmode);
+ }
+
+ /* Lock namespace. */
+ if (nspid != oldnspid)
+ LockDatabaseObject(NamespaceRelationId, nspid, 0, AccessShareLock);
+
+ /* Lock relation, if required if and we have permission. */
+ if (lockmode != NoLock && OidIsValid(relid))
+ {
+ if (!pg_class_ownercheck(relid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(relid)),
+ relation->relname);
+ if (relid != oldrelid)
+ LockRelationOid(relid, lockmode);
+ }
+
+ /* If no invalidation message were processed, we're done! */
+ if (inval_count == SharedInvalidMessageCounter)
+ break;
+
+ /* Something may have changed, so recheck our work. */
+ retry = true;
+ oldrelid = relid;
+ oldnspid = nspid;
+ }
+
+ RangeVarAdjustRelationPersistence(relation, nspid);
+ if (existing_relation_id != NULL)
+ *existing_relation_id = relid;
+ return nspid;
+}
+
+/*
+ * Adjust the relpersistence for an about-to-be-created relation based on the
+ * creation namespace, and throw an error for invalid combinations.
+ */
+void
+RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
+{
+ switch (newRelation->relpersistence)
+ {
+ case RELPERSISTENCE_TEMP:
+ if (!isTempOrTempToastNamespace(nspid))
+ {
+ if (isAnyTempNamespace(nspid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot create relations in temporary schemas of other sessions")));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot create temporary relation in non-temporary schema")));
+ }
+ break;
+ case RELPERSISTENCE_PERMANENT:
+ if (isTempOrTempToastNamespace(nspid))
+ newRelation->relpersistence = RELPERSISTENCE_TEMP;
+ else if (isAnyTempNamespace(nspid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot create relations in temporary schemas of other sessions")));
+ break;
+ default:
+ if (isAnyTempNamespace(nspid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("only temporary relations may be created in temporary schemas")));
+ }
+}
+
+/*
+ * RelnameGetRelid
+ * Try to resolve an unqualified relation name.
+ * Returns OID if relation found in search path, else InvalidOid.
+ */
+Oid
+RelnameGetRelid(const char *relname)
+{
+ Oid relid;
+ ListCell *l;
+
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ relid = get_relname_relid(relname, namespaceId);
+ if (OidIsValid(relid))
+ return relid;
+ }
+
+ /* Not found in path */
+ return InvalidOid;
+}
+
+
+/*
+ * RelationIsVisible
+ * Determine whether a relation (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified relation name".
+ */
+bool
+RelationIsVisible(Oid relid)
+{
+ HeapTuple reltup;
+ Form_pg_class relform;
+ Oid relnamespace;
+ bool visible;
+
+ reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(reltup))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+ relform = (Form_pg_class) GETSTRUCT(reltup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ relnamespace = relform->relnamespace;
+ if (relnamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, relnamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another relation of the same name earlier in the path. So
+ * we must do a slow check for conflicting relations.
+ */
+ char *relname = NameStr(relform->relname);
+ ListCell *l;
+
+ visible = false;
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == relnamespace)
+ {
+ /* Found it first in path */
+ visible = true;
+ break;
+ }
+ if (OidIsValid(get_relname_relid(relname, namespaceId)))
+ {
+ /* Found something else first in path */
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(reltup);
+
+ return visible;
+}
+
+
+/*
+ * TypenameGetTypid
+ * Wrapper for binary compatibility.
+ */
+Oid
+TypenameGetTypid(const char *typname)
+{
+ return TypenameGetTypidExtended(typname, true);
+}
+
+/*
+ * TypenameGetTypidExtended
+ * Try to resolve an unqualified datatype name.
+ * Returns OID if type found in search path, else InvalidOid.
+ *
+ * This is essentially the same as RelnameGetRelid.
+ */
+Oid
+TypenameGetTypidExtended(const char *typname, bool temp_ok)
+{
+ Oid typid;
+ ListCell *l;
+
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (!temp_ok && namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ typid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
+ PointerGetDatum(typname),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(typid))
+ return typid;
+ }
+
+ /* Not found in path */
+ return InvalidOid;
+}
+
+/*
+ * TypeIsVisible
+ * Determine whether a type (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified type name".
+ */
+bool
+TypeIsVisible(Oid typid)
+{
+ HeapTuple typtup;
+ Form_pg_type typform;
+ Oid typnamespace;
+ bool visible;
+
+ typtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
+ if (!HeapTupleIsValid(typtup))
+ elog(ERROR, "cache lookup failed for type %u", typid);
+ typform = (Form_pg_type) GETSTRUCT(typtup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ typnamespace = typform->typnamespace;
+ if (typnamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, typnamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another type of the same name earlier in the path. So we
+ * must do a slow check for conflicting types.
+ */
+ char *typname = NameStr(typform->typname);
+ ListCell *l;
+
+ visible = false;
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == typnamespace)
+ {
+ /* Found it first in path */
+ visible = true;
+ break;
+ }
+ if (SearchSysCacheExists2(TYPENAMENSP,
+ PointerGetDatum(typname),
+ ObjectIdGetDatum(namespaceId)))
+ {
+ /* Found something else first in path */
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(typtup);
+
+ return visible;
+}
+
+
+/*
+ * FuncnameGetCandidates
+ * Given a possibly-qualified function name and argument count,
+ * retrieve a list of the possible matches.
+ *
+ * If nargs is -1, we return all functions matching the given name,
+ * regardless of argument count. (argnames must be NIL, and expand_variadic
+ * and expand_defaults must be false, in this case.)
+ *
+ * If argnames isn't NIL, we are considering a named- or mixed-notation call,
+ * and only functions having all the listed argument names will be returned.
+ * (We assume that length(argnames) <= nargs and all the passed-in names are
+ * distinct.) The returned structs will include an argnumbers array showing
+ * the actual argument index for each logical argument position.
+ *
+ * If expand_variadic is true, then variadic functions having the same number
+ * or fewer arguments will be retrieved, with the variadic argument and any
+ * additional argument positions filled with the variadic element type.
+ * nvargs in the returned struct is set to the number of such arguments.
+ * If expand_variadic is false, variadic arguments are not treated specially,
+ * and the returned nvargs will always be zero.
+ *
+ * If expand_defaults is true, functions that could match after insertion of
+ * default argument values will also be retrieved. In this case the returned
+ * structs could have nargs > passed-in nargs, and ndargs is set to the number
+ * of additional args (which can be retrieved from the function's
+ * proargdefaults entry).
+ *
+ * It is not possible for nvargs and ndargs to both be nonzero in the same
+ * list entry, since default insertion allows matches to functions with more
+ * than nargs arguments while the variadic transformation requires the same
+ * number or less.
+ *
+ * When argnames isn't NIL, the returned args[] type arrays are not ordered
+ * according to the functions' declarations, but rather according to the call:
+ * first any positional arguments, then the named arguments, then defaulted
+ * arguments (if needed and allowed by expand_defaults). The argnumbers[]
+ * array can be used to map this back to the catalog information.
+ * argnumbers[k] is set to the proargtypes index of the k'th call argument.
+ *
+ * We search a single namespace if the function name is qualified, else
+ * all namespaces in the search path. In the multiple-namespace case,
+ * we arrange for entries in earlier namespaces to mask identical entries in
+ * later namespaces.
+ *
+ * When expanding variadics, we arrange for non-variadic functions to mask
+ * variadic ones if the expanded argument list is the same. It is still
+ * possible for there to be conflicts between different variadic functions,
+ * however.
+ *
+ * It is guaranteed that the return list will never contain multiple entries
+ * with identical argument lists. When expand_defaults is true, the entries
+ * could have more than nargs positions, but we still guarantee that they are
+ * distinct in the first nargs positions. However, if argnames isn't NIL or
+ * either expand_variadic or expand_defaults is true, there might be multiple
+ * candidate functions that expand to identical argument lists. Rather than
+ * throw error here, we report such situations by returning a single entry
+ * with oid = 0 that represents a set of such conflicting candidates.
+ * The caller might end up discarding such an entry anyway, but if it selects
+ * such an entry it should react as though the call were ambiguous.
+ *
+ * If missing_ok is true, an empty list (NULL) is returned if the name was
+ * schema- qualified with a schema that does not exist. Likewise if no
+ * candidate is found for other reasons.
+ */
+FuncCandidateList
+FuncnameGetCandidates(List *names, int nargs, List *argnames,
+ bool expand_variadic, bool expand_defaults,
+ bool missing_ok)
+{
+ FuncCandidateList resultList = NULL;
+ bool any_special = false;
+ char *schemaname;
+ char *funcname;
+ Oid namespaceId;
+ CatCList *catlist;
+ int i;
+
+ /* check for caller error */
+ Assert(nargs >= 0 || !(expand_variadic | expand_defaults));
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, &funcname);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (!OidIsValid(namespaceId))
+ return NULL;
+ }
+ else
+ {
+ /* flag to indicate we need namespace search */
+ namespaceId = InvalidOid;
+ recomputeNamespacePath();
+ }
+
+ /* Search syscache by name only */
+ catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(funcname));
+
+ for (i = 0; i < catlist->n_members; i++)
+ {
+ HeapTuple proctup = &catlist->members[i]->tuple;
+ Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
+ int pronargs = procform->pronargs;
+ int effective_nargs;
+ int pathpos = 0;
+ bool variadic;
+ bool use_defaults;
+ Oid va_elem_type;
+ int *argnumbers = NULL;
+ FuncCandidateList newResult;
+
+ if (OidIsValid(namespaceId))
+ {
+ /* Consider only procs in specified namespace */
+ if (procform->pronamespace != namespaceId)
+ continue;
+ }
+ else
+ {
+ /*
+ * Consider only procs that are in the search path and are not in
+ * the temp namespace.
+ */
+ ListCell *nsp;
+
+ foreach(nsp, activeSearchPath)
+ {
+ if (procform->pronamespace == lfirst_oid(nsp) &&
+ procform->pronamespace != myTempNamespace)
+ break;
+ pathpos++;
+ }
+ if (nsp == NULL)
+ continue; /* proc is not in search path */
+ }
+
+ if (argnames != NIL)
+ {
+ /*
+ * Call uses named or mixed notation
+ *
+ * Named or mixed notation can match a variadic function only if
+ * expand_variadic is off; otherwise there is no way to match the
+ * presumed-nameless parameters expanded from the variadic array.
+ */
+ if (OidIsValid(procform->provariadic) && expand_variadic)
+ continue;
+ va_elem_type = InvalidOid;
+ variadic = false;
+
+ /*
+ * Check argument count.
+ */
+ Assert(nargs >= 0); /* -1 not supported with argnames */
+
+ if (pronargs > nargs && expand_defaults)
+ {
+ /* Ignore if not enough default expressions */
+ if (nargs + procform->pronargdefaults < pronargs)
+ continue;
+ use_defaults = true;
+ }
+ else
+ use_defaults = false;
+
+ /* Ignore if it doesn't match requested argument count */
+ if (pronargs != nargs && !use_defaults)
+ continue;
+
+ /* Check for argument name match, generate positional mapping */
+ if (!MatchNamedCall(proctup, nargs, argnames,
+ &argnumbers))
+ continue;
+
+ /* Named argument matching is always "special" */
+ any_special = true;
+ }
+ else
+ {
+ /*
+ * Call uses positional notation
+ *
+ * Check if function is variadic, and get variadic element type if
+ * so. If expand_variadic is false, we should just ignore
+ * variadic-ness.
+ */
+ if (pronargs <= nargs && expand_variadic)
+ {
+ va_elem_type = procform->provariadic;
+ variadic = OidIsValid(va_elem_type);
+ any_special |= variadic;
+ }
+ else
+ {
+ va_elem_type = InvalidOid;
+ variadic = false;
+ }
+
+ /*
+ * Check if function can match by using parameter defaults.
+ */
+ if (pronargs > nargs && expand_defaults)
+ {
+ /* Ignore if not enough default expressions */
+ if (nargs + procform->pronargdefaults < pronargs)
+ continue;
+ use_defaults = true;
+ any_special = true;
+ }
+ else
+ use_defaults = false;
+
+ /* Ignore if it doesn't match requested argument count */
+ if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
+ continue;
+ }
+
+ /*
+ * We must compute the effective argument list so that we can easily
+ * compare it to earlier results. We waste a palloc cycle if it gets
+ * masked by an earlier result, but really that's a pretty infrequent
+ * case so it's not worth worrying about.
+ */
+ effective_nargs = Max(pronargs, nargs);
+ newResult = (FuncCandidateList)
+ palloc(offsetof(struct _FuncCandidateList, args) +
+ effective_nargs * sizeof(Oid));
+ newResult->pathpos = pathpos;
+ newResult->oid = procform->oid;
+ newResult->nargs = effective_nargs;
+ newResult->argnumbers = argnumbers;
+ if (argnumbers)
+ {
+ /* Re-order the argument types into call's logical order */
+ Oid *proargtypes = procform->proargtypes.values;
+ int i;
+
+ for (i = 0; i < pronargs; i++)
+ newResult->args[i] = proargtypes[argnumbers[i]];
+ }
+ else
+ {
+ /* Simple positional case, just copy proargtypes as-is */
+ memcpy(newResult->args, procform->proargtypes.values,
+ pronargs * sizeof(Oid));
+ }
+ if (variadic)
+ {
+ int i;
+
+ newResult->nvargs = effective_nargs - pronargs + 1;
+ /* Expand variadic argument into N copies of element type */
+ for (i = pronargs - 1; i < effective_nargs; i++)
+ newResult->args[i] = va_elem_type;
+ }
+ else
+ newResult->nvargs = 0;
+ newResult->ndargs = use_defaults ? pronargs - nargs : 0;
+
+ /*
+ * Does it have the same arguments as something we already accepted?
+ * If so, decide what to do to avoid returning duplicate argument
+ * lists. We can skip this check for the single-namespace case if no
+ * special (named, variadic or defaults) match has been made, since
+ * then the unique index on pg_proc guarantees all the matches have
+ * different argument lists.
+ */
+ if (resultList != NULL &&
+ (any_special || !OidIsValid(namespaceId)))
+ {
+ /*
+ * If we have an ordered list from SearchSysCacheList (the normal
+ * case), then any conflicting proc must immediately adjoin this
+ * one in the list, so we only need to look at the newest result
+ * item. If we have an unordered list, we have to scan the whole
+ * result list. Also, if either the current candidate or any
+ * previous candidate is a special match, we can't assume that
+ * conflicts are adjacent.
+ *
+ * We ignore defaulted arguments in deciding what is a match.
+ */
+ FuncCandidateList prevResult;
+
+ if (catlist->ordered && !any_special)
+ {
+ /* ndargs must be 0 if !any_special */
+ if (effective_nargs == resultList->nargs &&
+ memcmp(newResult->args,
+ resultList->args,
+ effective_nargs * sizeof(Oid)) == 0)
+ prevResult = resultList;
+ else
+ prevResult = NULL;
+ }
+ else
+ {
+ int cmp_nargs = newResult->nargs - newResult->ndargs;
+
+ for (prevResult = resultList;
+ prevResult;
+ prevResult = prevResult->next)
+ {
+ if (cmp_nargs == prevResult->nargs - prevResult->ndargs &&
+ memcmp(newResult->args,
+ prevResult->args,
+ cmp_nargs * sizeof(Oid)) == 0)
+ break;
+ }
+ }
+
+ if (prevResult)
+ {
+ /*
+ * We have a match with a previous result. Decide which one
+ * to keep, or mark it ambiguous if we can't decide. The
+ * logic here is preference > 0 means prefer the old result,
+ * preference < 0 means prefer the new, preference = 0 means
+ * ambiguous.
+ */
+ int preference;
+
+ if (pathpos != prevResult->pathpos)
+ {
+ /*
+ * Prefer the one that's earlier in the search path.
+ */
+ preference = pathpos - prevResult->pathpos;
+ }
+ else if (variadic && prevResult->nvargs == 0)
+ {
+ /*
+ * With variadic functions we could have, for example,
+ * both foo(numeric) and foo(variadic numeric[]) in the
+ * same namespace; if so we prefer the non-variadic match
+ * on efficiency grounds.
+ */
+ preference = 1;
+ }
+ else if (!variadic && prevResult->nvargs > 0)
+ {
+ preference = -1;
+ }
+ else
+ {
+ /*----------
+ * We can't decide. This can happen with, for example,
+ * both foo(numeric, variadic numeric[]) and
+ * foo(variadic numeric[]) in the same namespace, or
+ * both foo(int) and foo (int, int default something)
+ * in the same namespace, or both foo(a int, b text)
+ * and foo(b text, a int) in the same namespace.
+ *----------
+ */
+ preference = 0;
+ }
+
+ if (preference > 0)
+ {
+ /* keep previous result */
+ pfree(newResult);
+ continue;
+ }
+ else if (preference < 0)
+ {
+ /* remove previous result from the list */
+ if (prevResult == resultList)
+ resultList = prevResult->next;
+ else
+ {
+ FuncCandidateList prevPrevResult;
+
+ for (prevPrevResult = resultList;
+ prevPrevResult;
+ prevPrevResult = prevPrevResult->next)
+ {
+ if (prevResult == prevPrevResult->next)
+ {
+ prevPrevResult->next = prevResult->next;
+ break;
+ }
+ }
+ Assert(prevPrevResult); /* assert we found it */
+ }
+ pfree(prevResult);
+ /* fall through to add newResult to list */
+ }
+ else
+ {
+ /* mark old result as ambiguous, discard new */
+ prevResult->oid = InvalidOid;
+ pfree(newResult);
+ continue;
+ }
+ }
+ }
+
+ /*
+ * Okay to add it to result list
+ */
+ newResult->next = resultList;
+ resultList = newResult;
+ }
+
+ ReleaseSysCacheList(catlist);
+
+ return resultList;
+}
+
+/*
+ * MatchNamedCall
+ * Given a pg_proc heap tuple and a call's list of argument names,
+ * check whether the function could match the call.
+ *
+ * The call could match if all supplied argument names are accepted by
+ * the function, in positions after the last positional argument, and there
+ * are defaults for all unsupplied arguments.
+ *
+ * The number of positional arguments is nargs - list_length(argnames).
+ * Note caller has already done basic checks on argument count.
+ *
+ * On match, return true and fill *argnumbers with a palloc'd array showing
+ * the mapping from call argument positions to actual function argument
+ * numbers. Defaulted arguments are included in this map, at positions
+ * after the last supplied argument.
+ */
+static bool
+MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
+ int **argnumbers)
+{
+ Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
+ int pronargs = procform->pronargs;
+ int numposargs = nargs - list_length(argnames);
+ int pronallargs;
+ Oid *p_argtypes;
+ char **p_argnames;
+ char *p_argmodes;
+ bool arggiven[FUNC_MAX_ARGS];
+ bool isnull;
+ int ap; /* call args position */
+ int pp; /* proargs position */
+ ListCell *lc;
+
+ Assert(argnames != NIL);
+ Assert(numposargs >= 0);
+ Assert(nargs <= pronargs);
+
+ /* Ignore this function if its proargnames is null */
+ (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proargnames,
+ &isnull);
+ if (isnull)
+ return false;
+
+ /* OK, let's extract the argument names and types */
+ pronallargs = get_func_arg_info(proctup,
+ &p_argtypes, &p_argnames, &p_argmodes);
+ Assert(p_argnames != NULL);
+
+ /* initialize state for matching */
+ *argnumbers = (int *) palloc(pronargs * sizeof(int));
+ memset(arggiven, false, pronargs * sizeof(bool));
+
+ /* there are numposargs positional args before the named args */
+ for (ap = 0; ap < numposargs; ap++)
+ {
+ (*argnumbers)[ap] = ap;
+ arggiven[ap] = true;
+ }
+
+ /* now examine the named args */
+ foreach(lc, argnames)
+ {
+ char *argname = (char *) lfirst(lc);
+ bool found;
+ int i;
+
+ pp = 0;
+ found = false;
+ for (i = 0; i < pronallargs; i++)
+ {
+ /* consider only input parameters */
+ if (p_argmodes &&
+ (p_argmodes[i] != FUNC_PARAM_IN &&
+ p_argmodes[i] != FUNC_PARAM_INOUT &&
+ p_argmodes[i] != FUNC_PARAM_VARIADIC))
+ continue;
+ if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
+ {
+ /* fail if argname matches a positional argument */
+ if (arggiven[pp])
+ return false;
+ arggiven[pp] = true;
+ (*argnumbers)[ap] = pp;
+ found = true;
+ break;
+ }
+ /* increase pp only for input parameters */
+ pp++;
+ }
+ /* if name isn't in proargnames, fail */
+ if (!found)
+ return false;
+ ap++;
+ }
+
+ Assert(ap == nargs); /* processed all actual parameters */
+
+ /* Check for default arguments */
+ if (nargs < pronargs)
+ {
+ int first_arg_with_default = pronargs - procform->pronargdefaults;
+
+ for (pp = numposargs; pp < pronargs; pp++)
+ {
+ if (arggiven[pp])
+ continue;
+ /* fail if arg not given and no default available */
+ if (pp < first_arg_with_default)
+ return false;
+ (*argnumbers)[ap++] = pp;
+ }
+ }
+
+ Assert(ap == pronargs); /* processed all function parameters */
+
+ return true;
+}
+
+/*
+ * FunctionIsVisible
+ * Determine whether a function (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified function name with exact argument matches".
+ */
+bool
+FunctionIsVisible(Oid funcid)
+{
+ HeapTuple proctup;
+ Form_pg_proc procform;
+ Oid pronamespace;
+ bool visible;
+
+ proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
+ if (!HeapTupleIsValid(proctup))
+ elog(ERROR, "cache lookup failed for function %u", funcid);
+ procform = (Form_pg_proc) GETSTRUCT(proctup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ pronamespace = procform->pronamespace;
+ if (pronamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, pronamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another proc of the same name and arguments earlier in
+ * the path. So we must do a slow check to see if this is the same
+ * proc that would be found by FuncnameGetCandidates.
+ */
+ char *proname = NameStr(procform->proname);
+ int nargs = procform->pronargs;
+ FuncCandidateList clist;
+
+ visible = false;
+
+ clist = FuncnameGetCandidates(list_make1(makeString(proname)),
+ nargs, NIL, false, false, false);
+
+ for (; clist; clist = clist->next)
+ {
+ if (memcmp(clist->args, procform->proargtypes.values,
+ nargs * sizeof(Oid)) == 0)
+ {
+ /* Found the expected entry; is it the right proc? */
+ visible = (clist->oid == funcid);
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(proctup);
+
+ return visible;
+}
+
+
+/*
+ * OpernameGetOprid
+ * Given a possibly-qualified operator name and exact input datatypes,
+ * look up the operator. Returns InvalidOid if not found.
+ *
+ * Pass oprleft = InvalidOid for a prefix op, oprright = InvalidOid for
+ * a postfix op.
+ *
+ * If the operator name is not schema-qualified, it is sought in the current
+ * namespace search path. If the name is schema-qualified and the given
+ * schema does not exist, InvalidOid is returned.
+ */
+Oid
+OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
+{
+ char *schemaname;
+ char *opername;
+ CatCList *catlist;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, &opername);
+
+ if (schemaname)
+ {
+ /* search only in exact schema given */
+ Oid namespaceId;
+
+ namespaceId = LookupExplicitNamespace(schemaname, true);
+ if (OidIsValid(namespaceId))
+ {
+ HeapTuple opertup;
+
+ opertup = SearchSysCache4(OPERNAMENSP,
+ CStringGetDatum(opername),
+ ObjectIdGetDatum(oprleft),
+ ObjectIdGetDatum(oprright),
+ ObjectIdGetDatum(namespaceId));
+ if (HeapTupleIsValid(opertup))
+ {
+ Form_pg_operator operclass = (Form_pg_operator) GETSTRUCT(opertup);
+ Oid result = operclass->oid;
+
+ ReleaseSysCache(opertup);
+ return result;
+ }
+ }
+
+ return InvalidOid;
+ }
+
+ /* Search syscache by name and argument types */
+ catlist = SearchSysCacheList3(OPERNAMENSP,
+ CStringGetDatum(opername),
+ ObjectIdGetDatum(oprleft),
+ ObjectIdGetDatum(oprright));
+
+ if (catlist->n_members == 0)
+ {
+ /* no hope, fall out early */
+ ReleaseSysCacheList(catlist);
+ return InvalidOid;
+ }
+
+ /*
+ * We have to find the list member that is first in the search path, if
+ * there's more than one. This doubly-nested loop looks ugly, but in
+ * practice there should usually be few catlist members.
+ */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+ int i;
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ for (i = 0; i < catlist->n_members; i++)
+ {
+ HeapTuple opertup = &catlist->members[i]->tuple;
+ Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
+
+ if (operform->oprnamespace == namespaceId)
+ {
+ Oid result = operform->oid;
+
+ ReleaseSysCacheList(catlist);
+ return result;
+ }
+ }
+ }
+
+ ReleaseSysCacheList(catlist);
+ return InvalidOid;
+}
+
+/*
+ * OpernameGetCandidates
+ * Given a possibly-qualified operator name and operator kind,
+ * retrieve a list of the possible matches.
+ *
+ * If oprkind is '\0', we return all operators matching the given name,
+ * regardless of arguments.
+ *
+ * We search a single namespace if the operator name is qualified, else
+ * all namespaces in the search path. The return list will never contain
+ * multiple entries with identical argument lists --- in the multiple-
+ * namespace case, we arrange for entries in earlier namespaces to mask
+ * identical entries in later namespaces.
+ *
+ * The returned items always have two args[] entries --- one or the other
+ * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too.
+ */
+FuncCandidateList
+OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
+{
+ FuncCandidateList resultList = NULL;
+ char *resultSpace = NULL;
+ int nextResult = 0;
+ char *schemaname;
+ char *opername;
+ Oid namespaceId;
+ CatCList *catlist;
+ int i;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, &opername);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_schema_ok);
+ if (missing_schema_ok && !OidIsValid(namespaceId))
+ return NULL;
+ }
+ else
+ {
+ /* flag to indicate we need namespace search */
+ namespaceId = InvalidOid;
+ recomputeNamespacePath();
+ }
+
+ /* Search syscache by name only */
+ catlist = SearchSysCacheList1(OPERNAMENSP, CStringGetDatum(opername));
+
+ /*
+ * In typical scenarios, most if not all of the operators found by the
+ * catcache search will end up getting returned; and there can be quite a
+ * few, for common operator names such as '=' or '+'. To reduce the time
+ * spent in palloc, we allocate the result space as an array large enough
+ * to hold all the operators. The original coding of this routine did a
+ * separate palloc for each operator, but profiling revealed that the
+ * pallocs used an unreasonably large fraction of parsing time.
+ */
+#define SPACE_PER_OP MAXALIGN(offsetof(struct _FuncCandidateList, args) + \
+ 2 * sizeof(Oid))
+
+ if (catlist->n_members > 0)
+ resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
+
+ for (i = 0; i < catlist->n_members; i++)
+ {
+ HeapTuple opertup = &catlist->members[i]->tuple;
+ Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
+ int pathpos = 0;
+ FuncCandidateList newResult;
+
+ /* Ignore operators of wrong kind, if specific kind requested */
+ if (oprkind && operform->oprkind != oprkind)
+ continue;
+
+ if (OidIsValid(namespaceId))
+ {
+ /* Consider only opers in specified namespace */
+ if (operform->oprnamespace != namespaceId)
+ continue;
+ /* No need to check args, they must all be different */
+ }
+ else
+ {
+ /*
+ * Consider only opers that are in the search path and are not in
+ * the temp namespace.
+ */
+ ListCell *nsp;
+
+ foreach(nsp, activeSearchPath)
+ {
+ if (operform->oprnamespace == lfirst_oid(nsp) &&
+ operform->oprnamespace != myTempNamespace)
+ break;
+ pathpos++;
+ }
+ if (nsp == NULL)
+ continue; /* oper is not in search path */
+
+ /*
+ * Okay, it's in the search path, but does it have the same
+ * arguments as something we already accepted? If so, keep only
+ * the one that appears earlier in the search path.
+ *
+ * If we have an ordered list from SearchSysCacheList (the normal
+ * case), then any conflicting oper must immediately adjoin this
+ * one in the list, so we only need to look at the newest result
+ * item. If we have an unordered list, we have to scan the whole
+ * result list.
+ */
+ if (resultList)
+ {
+ FuncCandidateList prevResult;
+
+ if (catlist->ordered)
+ {
+ if (operform->oprleft == resultList->args[0] &&
+ operform->oprright == resultList->args[1])
+ prevResult = resultList;
+ else
+ prevResult = NULL;
+ }
+ else
+ {
+ for (prevResult = resultList;
+ prevResult;
+ prevResult = prevResult->next)
+ {
+ if (operform->oprleft == prevResult->args[0] &&
+ operform->oprright == prevResult->args[1])
+ break;
+ }
+ }
+ if (prevResult)
+ {
+ /* We have a match with a previous result */
+ Assert(pathpos != prevResult->pathpos);
+ if (pathpos > prevResult->pathpos)
+ continue; /* keep previous result */
+ /* replace previous result */
+ prevResult->pathpos = pathpos;
+ prevResult->oid = operform->oid;
+ continue; /* args are same, of course */
+ }
+ }
+ }
+
+ /*
+ * Okay to add it to result list
+ */
+ newResult = (FuncCandidateList) (resultSpace + nextResult);
+ nextResult += SPACE_PER_OP;
+
+ newResult->pathpos = pathpos;
+ newResult->oid = operform->oid;
+ newResult->nargs = 2;
+ newResult->nvargs = 0;
+ newResult->ndargs = 0;
+ newResult->argnumbers = NULL;
+ newResult->args[0] = operform->oprleft;
+ newResult->args[1] = operform->oprright;
+ newResult->next = resultList;
+ resultList = newResult;
+ }
+
+ ReleaseSysCacheList(catlist);
+
+ return resultList;
+}
+
+/*
+ * OperatorIsVisible
+ * Determine whether an operator (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified operator name with exact argument matches".
+ */
+bool
+OperatorIsVisible(Oid oprid)
+{
+ HeapTuple oprtup;
+ Form_pg_operator oprform;
+ Oid oprnamespace;
+ bool visible;
+
+ oprtup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
+ if (!HeapTupleIsValid(oprtup))
+ elog(ERROR, "cache lookup failed for operator %u", oprid);
+ oprform = (Form_pg_operator) GETSTRUCT(oprtup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ oprnamespace = oprform->oprnamespace;
+ if (oprnamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, oprnamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another operator of the same name and arguments earlier
+ * in the path. So we must do a slow check to see if this is the same
+ * operator that would be found by OpernameGetOprid.
+ */
+ char *oprname = NameStr(oprform->oprname);
+
+ visible = (OpernameGetOprid(list_make1(makeString(oprname)),
+ oprform->oprleft, oprform->oprright)
+ == oprid);
+ }
+
+ ReleaseSysCache(oprtup);
+
+ return visible;
+}
+
+
+/*
+ * OpclassnameGetOpcid
+ * Try to resolve an unqualified index opclass name.
+ * Returns OID if opclass found in search path, else InvalidOid.
+ *
+ * This is essentially the same as TypenameGetTypid, but we have to have
+ * an extra argument for the index AM OID.
+ */
+Oid
+OpclassnameGetOpcid(Oid amid, const char *opcname)
+{
+ Oid opcid;
+ ListCell *l;
+
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ opcid = GetSysCacheOid3(CLAAMNAMENSP, Anum_pg_opclass_oid,
+ ObjectIdGetDatum(amid),
+ PointerGetDatum(opcname),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(opcid))
+ return opcid;
+ }
+
+ /* Not found in path */
+ return InvalidOid;
+}
+
+/*
+ * OpclassIsVisible
+ * Determine whether an opclass (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified opclass name".
+ */
+bool
+OpclassIsVisible(Oid opcid)
+{
+ HeapTuple opctup;
+ Form_pg_opclass opcform;
+ Oid opcnamespace;
+ bool visible;
+
+ opctup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcid));
+ if (!HeapTupleIsValid(opctup))
+ elog(ERROR, "cache lookup failed for opclass %u", opcid);
+ opcform = (Form_pg_opclass) GETSTRUCT(opctup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ opcnamespace = opcform->opcnamespace;
+ if (opcnamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, opcnamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another opclass of the same name earlier in the path. So
+ * we must do a slow check to see if this opclass would be found by
+ * OpclassnameGetOpcid.
+ */
+ char *opcname = NameStr(opcform->opcname);
+
+ visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
+ }
+
+ ReleaseSysCache(opctup);
+
+ return visible;
+}
+
+/*
+ * OpfamilynameGetOpfid
+ * Try to resolve an unqualified index opfamily name.
+ * Returns OID if opfamily found in search path, else InvalidOid.
+ *
+ * This is essentially the same as TypenameGetTypid, but we have to have
+ * an extra argument for the index AM OID.
+ */
+Oid
+OpfamilynameGetOpfid(Oid amid, const char *opfname)
+{
+ Oid opfid;
+ ListCell *l;
+
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ opfid = GetSysCacheOid3(OPFAMILYAMNAMENSP, Anum_pg_opfamily_oid,
+ ObjectIdGetDatum(amid),
+ PointerGetDatum(opfname),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(opfid))
+ return opfid;
+ }
+
+ /* Not found in path */
+ return InvalidOid;
+}
+
+/*
+ * OpfamilyIsVisible
+ * Determine whether an opfamily (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified opfamily name".
+ */
+bool
+OpfamilyIsVisible(Oid opfid)
+{
+ HeapTuple opftup;
+ Form_pg_opfamily opfform;
+ Oid opfnamespace;
+ bool visible;
+
+ opftup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
+ if (!HeapTupleIsValid(opftup))
+ elog(ERROR, "cache lookup failed for opfamily %u", opfid);
+ opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ opfnamespace = opfform->opfnamespace;
+ if (opfnamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, opfnamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another opfamily of the same name earlier in the path. So
+ * we must do a slow check to see if this opfamily would be found by
+ * OpfamilynameGetOpfid.
+ */
+ char *opfname = NameStr(opfform->opfname);
+
+ visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
+ }
+
+ ReleaseSysCache(opftup);
+
+ return visible;
+}
+
+/*
+ * lookup_collation
+ * If there's a collation of the given name/namespace, and it works
+ * with the given encoding, return its OID. Else return InvalidOid.
+ */
+static Oid
+lookup_collation(const char *collname, Oid collnamespace, int32 encoding)
+{
+ Oid collid;
+ HeapTuple colltup;
+ Form_pg_collation collform;
+
+ /* Check for encoding-specific entry (exact match) */
+ collid = GetSysCacheOid3(COLLNAMEENCNSP, Anum_pg_collation_oid,
+ PointerGetDatum(collname),
+ Int32GetDatum(encoding),
+ ObjectIdGetDatum(collnamespace));
+ if (OidIsValid(collid))
+ return collid;
+
+ /*
+ * Check for any-encoding entry. This takes a bit more work: while libc
+ * collations with collencoding = -1 do work with all encodings, ICU
+ * collations only work with certain encodings, so we have to check that
+ * aspect before deciding it's a match.
+ */
+ colltup = SearchSysCache3(COLLNAMEENCNSP,
+ PointerGetDatum(collname),
+ Int32GetDatum(-1),
+ ObjectIdGetDatum(collnamespace));
+ if (!HeapTupleIsValid(colltup))
+ return InvalidOid;
+ collform = (Form_pg_collation) GETSTRUCT(colltup);
+ if (collform->collprovider == COLLPROVIDER_ICU)
+ {
+ if (is_encoding_supported_by_icu(encoding))
+ collid = collform->oid;
+ else
+ collid = InvalidOid;
+ }
+ else
+ {
+ collid = collform->oid;
+ }
+ ReleaseSysCache(colltup);
+ return collid;
+}
+
+/*
+ * CollationGetCollid
+ * Try to resolve an unqualified collation name.
+ * Returns OID if collation found in search path, else InvalidOid.
+ *
+ * Note that this will only find collations that work with the current
+ * database's encoding.
+ */
+Oid
+CollationGetCollid(const char *collname)
+{
+ int32 dbencoding = GetDatabaseEncoding();
+ ListCell *l;
+
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+ Oid collid;
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ collid = lookup_collation(collname, namespaceId, dbencoding);
+ if (OidIsValid(collid))
+ return collid;
+ }
+
+ /* Not found in path */
+ return InvalidOid;
+}
+
+/*
+ * CollationIsVisible
+ * Determine whether a collation (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified collation name".
+ *
+ * Note that only collations that work with the current database's encoding
+ * will be considered visible.
+ */
+bool
+CollationIsVisible(Oid collid)
+{
+ HeapTuple colltup;
+ Form_pg_collation collform;
+ Oid collnamespace;
+ bool visible;
+
+ colltup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
+ if (!HeapTupleIsValid(colltup))
+ elog(ERROR, "cache lookup failed for collation %u", collid);
+ collform = (Form_pg_collation) GETSTRUCT(colltup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ collnamespace = collform->collnamespace;
+ if (collnamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, collnamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another collation of the same name earlier in the path,
+ * or it might not work with the current DB encoding. So we must do a
+ * slow check to see if this collation would be found by
+ * CollationGetCollid.
+ */
+ char *collname = NameStr(collform->collname);
+
+ visible = (CollationGetCollid(collname) == collid);
+ }
+
+ ReleaseSysCache(colltup);
+
+ return visible;
+}
+
+
+/*
+ * ConversionGetConid
+ * Try to resolve an unqualified conversion name.
+ * Returns OID if conversion found in search path, else InvalidOid.
+ *
+ * This is essentially the same as RelnameGetRelid.
+ */
+Oid
+ConversionGetConid(const char *conname)
+{
+ Oid conid;
+ ListCell *l;
+
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ conid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
+ PointerGetDatum(conname),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(conid))
+ return conid;
+ }
+
+ /* Not found in path */
+ return InvalidOid;
+}
+
+/*
+ * ConversionIsVisible
+ * Determine whether a conversion (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified conversion name".
+ */
+bool
+ConversionIsVisible(Oid conid)
+{
+ HeapTuple contup;
+ Form_pg_conversion conform;
+ Oid connamespace;
+ bool visible;
+
+ contup = SearchSysCache1(CONVOID, ObjectIdGetDatum(conid));
+ if (!HeapTupleIsValid(contup))
+ elog(ERROR, "cache lookup failed for conversion %u", conid);
+ conform = (Form_pg_conversion) GETSTRUCT(contup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ connamespace = conform->connamespace;
+ if (connamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, connamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another conversion of the same name earlier in the path.
+ * So we must do a slow check to see if this conversion would be found
+ * by ConversionGetConid.
+ */
+ char *conname = NameStr(conform->conname);
+
+ visible = (ConversionGetConid(conname) == conid);
+ }
+
+ ReleaseSysCache(contup);
+
+ return visible;
+}
+
+/*
+ * get_statistics_object_oid - find a statistics object by possibly qualified name
+ *
+ * If not found, returns InvalidOid if missing_ok, else throws error
+ */
+Oid
+get_statistics_object_oid(List *names, bool missing_ok)
+{
+ char *schemaname;
+ char *stats_name;
+ Oid namespaceId;
+ Oid stats_oid = InvalidOid;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, &stats_name);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ stats_oid = InvalidOid;
+ else
+ stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
+ PointerGetDatum(stats_name),
+ ObjectIdGetDatum(namespaceId));
+ }
+ else
+ {
+ /* search for it in search path */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+ stats_oid = GetSysCacheOid2(STATEXTNAMENSP, Anum_pg_statistic_ext_oid,
+ PointerGetDatum(stats_name),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(stats_oid))
+ break;
+ }
+ }
+
+ if (!OidIsValid(stats_oid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("statistics object \"%s\" does not exist",
+ NameListToString(names))));
+
+ return stats_oid;
+}
+
+/*
+ * StatisticsObjIsVisible
+ * Determine whether a statistics object (identified by OID) is visible in
+ * the current search path. Visible means "would be found by searching
+ * for the unqualified statistics object name".
+ */
+bool
+StatisticsObjIsVisible(Oid relid)
+{
+ HeapTuple stxtup;
+ Form_pg_statistic_ext stxform;
+ Oid stxnamespace;
+ bool visible;
+
+ stxtup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(stxtup))
+ elog(ERROR, "cache lookup failed for statistics object %u", relid);
+ stxform = (Form_pg_statistic_ext) GETSTRUCT(stxtup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ stxnamespace = stxform->stxnamespace;
+ if (stxnamespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, stxnamespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another statistics object of the same name earlier in the
+ * path. So we must do a slow check for conflicting objects.
+ */
+ char *stxname = NameStr(stxform->stxname);
+ ListCell *l;
+
+ visible = false;
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == stxnamespace)
+ {
+ /* Found it first in path */
+ visible = true;
+ break;
+ }
+ if (SearchSysCacheExists2(STATEXTNAMENSP,
+ PointerGetDatum(stxname),
+ ObjectIdGetDatum(namespaceId)))
+ {
+ /* Found something else first in path */
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(stxtup);
+
+ return visible;
+}
+
+/*
+ * get_ts_parser_oid - find a TS parser by possibly qualified name
+ *
+ * If not found, returns InvalidOid if missing_ok, else throws error
+ */
+Oid
+get_ts_parser_oid(List *names, bool missing_ok)
+{
+ char *schemaname;
+ char *parser_name;
+ Oid namespaceId;
+ Oid prsoid = InvalidOid;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, &parser_name);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ prsoid = InvalidOid;
+ else
+ prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
+ PointerGetDatum(parser_name),
+ ObjectIdGetDatum(namespaceId));
+ }
+ else
+ {
+ /* search for it in search path */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ prsoid = GetSysCacheOid2(TSPARSERNAMENSP, Anum_pg_ts_parser_oid,
+ PointerGetDatum(parser_name),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(prsoid))
+ break;
+ }
+ }
+
+ if (!OidIsValid(prsoid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("text search parser \"%s\" does not exist",
+ NameListToString(names))));
+
+ return prsoid;
+}
+
+/*
+ * TSParserIsVisible
+ * Determine whether a parser (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified parser name".
+ */
+bool
+TSParserIsVisible(Oid prsId)
+{
+ HeapTuple tup;
+ Form_pg_ts_parser form;
+ Oid namespace;
+ bool visible;
+
+ tup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(prsId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search parser %u", prsId);
+ form = (Form_pg_ts_parser) GETSTRUCT(tup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ namespace = form->prsnamespace;
+ if (namespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, namespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another parser of the same name earlier in the path. So
+ * we must do a slow check for conflicting parsers.
+ */
+ char *name = NameStr(form->prsname);
+ ListCell *l;
+
+ visible = false;
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ if (namespaceId == namespace)
+ {
+ /* Found it first in path */
+ visible = true;
+ break;
+ }
+ if (SearchSysCacheExists2(TSPARSERNAMENSP,
+ PointerGetDatum(name),
+ ObjectIdGetDatum(namespaceId)))
+ {
+ /* Found something else first in path */
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(tup);
+
+ return visible;
+}
+
+/*
+ * get_ts_dict_oid - find a TS dictionary by possibly qualified name
+ *
+ * If not found, returns InvalidOid if missing_ok, else throws error
+ */
+Oid
+get_ts_dict_oid(List *names, bool missing_ok)
+{
+ char *schemaname;
+ char *dict_name;
+ Oid namespaceId;
+ Oid dictoid = InvalidOid;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, &dict_name);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ dictoid = InvalidOid;
+ else
+ dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
+ PointerGetDatum(dict_name),
+ ObjectIdGetDatum(namespaceId));
+ }
+ else
+ {
+ /* search for it in search path */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ dictoid = GetSysCacheOid2(TSDICTNAMENSP, Anum_pg_ts_dict_oid,
+ PointerGetDatum(dict_name),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(dictoid))
+ break;
+ }
+ }
+
+ if (!OidIsValid(dictoid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("text search dictionary \"%s\" does not exist",
+ NameListToString(names))));
+
+ return dictoid;
+}
+
+/*
+ * TSDictionaryIsVisible
+ * Determine whether a dictionary (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified dictionary name".
+ */
+bool
+TSDictionaryIsVisible(Oid dictId)
+{
+ HeapTuple tup;
+ Form_pg_ts_dict form;
+ Oid namespace;
+ bool visible;
+
+ tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search dictionary %u",
+ dictId);
+ form = (Form_pg_ts_dict) GETSTRUCT(tup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ namespace = form->dictnamespace;
+ if (namespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, namespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another dictionary of the same name earlier in the path.
+ * So we must do a slow check for conflicting dictionaries.
+ */
+ char *name = NameStr(form->dictname);
+ ListCell *l;
+
+ visible = false;
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ if (namespaceId == namespace)
+ {
+ /* Found it first in path */
+ visible = true;
+ break;
+ }
+ if (SearchSysCacheExists2(TSDICTNAMENSP,
+ PointerGetDatum(name),
+ ObjectIdGetDatum(namespaceId)))
+ {
+ /* Found something else first in path */
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(tup);
+
+ return visible;
+}
+
+/*
+ * get_ts_template_oid - find a TS template by possibly qualified name
+ *
+ * If not found, returns InvalidOid if missing_ok, else throws error
+ */
+Oid
+get_ts_template_oid(List *names, bool missing_ok)
+{
+ char *schemaname;
+ char *template_name;
+ Oid namespaceId;
+ Oid tmploid = InvalidOid;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, &template_name);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ tmploid = InvalidOid;
+ else
+ tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
+ PointerGetDatum(template_name),
+ ObjectIdGetDatum(namespaceId));
+ }
+ else
+ {
+ /* search for it in search path */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP, Anum_pg_ts_template_oid,
+ PointerGetDatum(template_name),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(tmploid))
+ break;
+ }
+ }
+
+ if (!OidIsValid(tmploid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("text search template \"%s\" does not exist",
+ NameListToString(names))));
+
+ return tmploid;
+}
+
+/*
+ * TSTemplateIsVisible
+ * Determine whether a template (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified template name".
+ */
+bool
+TSTemplateIsVisible(Oid tmplId)
+{
+ HeapTuple tup;
+ Form_pg_ts_template form;
+ Oid namespace;
+ bool visible;
+
+ tup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search template %u", tmplId);
+ form = (Form_pg_ts_template) GETSTRUCT(tup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ namespace = form->tmplnamespace;
+ if (namespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, namespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another template of the same name earlier in the path. So
+ * we must do a slow check for conflicting templates.
+ */
+ char *name = NameStr(form->tmplname);
+ ListCell *l;
+
+ visible = false;
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ if (namespaceId == namespace)
+ {
+ /* Found it first in path */
+ visible = true;
+ break;
+ }
+ if (SearchSysCacheExists2(TSTEMPLATENAMENSP,
+ PointerGetDatum(name),
+ ObjectIdGetDatum(namespaceId)))
+ {
+ /* Found something else first in path */
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(tup);
+
+ return visible;
+}
+
+/*
+ * get_ts_config_oid - find a TS config by possibly qualified name
+ *
+ * If not found, returns InvalidOid if missing_ok, else throws error
+ */
+Oid
+get_ts_config_oid(List *names, bool missing_ok)
+{
+ char *schemaname;
+ char *config_name;
+ Oid namespaceId;
+ Oid cfgoid = InvalidOid;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, &config_name);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ cfgoid = InvalidOid;
+ else
+ cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
+ PointerGetDatum(config_name),
+ ObjectIdGetDatum(namespaceId));
+ }
+ else
+ {
+ /* search for it in search path */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP, Anum_pg_ts_config_oid,
+ PointerGetDatum(config_name),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(cfgoid))
+ break;
+ }
+ }
+
+ if (!OidIsValid(cfgoid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("text search configuration \"%s\" does not exist",
+ NameListToString(names))));
+
+ return cfgoid;
+}
+
+/*
+ * TSConfigIsVisible
+ * Determine whether a text search configuration (identified by OID)
+ * is visible in the current search path. Visible means "would be found
+ * by searching for the unqualified text search configuration name".
+ */
+bool
+TSConfigIsVisible(Oid cfgid)
+{
+ HeapTuple tup;
+ Form_pg_ts_config form;
+ Oid namespace;
+ bool visible;
+
+ tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search configuration %u",
+ cfgid);
+ form = (Form_pg_ts_config) GETSTRUCT(tup);
+
+ recomputeNamespacePath();
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible. Items in
+ * the system namespace are surely in the path and so we needn't even do
+ * list_member_oid() for them.
+ */
+ namespace = form->cfgnamespace;
+ if (namespace != PG_CATALOG_NAMESPACE &&
+ !list_member_oid(activeSearchPath, namespace))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another configuration of the same name earlier in the
+ * path. So we must do a slow check for conflicting configurations.
+ */
+ char *name = NameStr(form->cfgname);
+ ListCell *l;
+
+ visible = false;
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ if (namespaceId == namespace)
+ {
+ /* Found it first in path */
+ visible = true;
+ break;
+ }
+ if (SearchSysCacheExists2(TSCONFIGNAMENSP,
+ PointerGetDatum(name),
+ ObjectIdGetDatum(namespaceId)))
+ {
+ /* Found something else first in path */
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(tup);
+
+ return visible;
+}
+
+
+/*
+ * DeconstructQualifiedName
+ * Given a possibly-qualified name expressed as a list of String nodes,
+ * extract the schema name and object name.
+ *
+ * *nspname_p is set to NULL if there is no explicit schema name.
+ */
+void
+DeconstructQualifiedName(List *names,
+ char **nspname_p,
+ char **objname_p)
+{
+ char *catalogname;
+ char *schemaname = NULL;
+ char *objname = NULL;
+
+ switch (list_length(names))
+ {
+ case 1:
+ objname = strVal(linitial(names));
+ break;
+ case 2:
+ schemaname = strVal(linitial(names));
+ objname = strVal(lsecond(names));
+ break;
+ case 3:
+ catalogname = strVal(linitial(names));
+ schemaname = strVal(lsecond(names));
+ objname = strVal(lthird(names));
+
+ /*
+ * We check the catalog name and then ignore it.
+ */
+ if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cross-database references are not implemented: %s",
+ NameListToString(names))));
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("improper qualified name (too many dotted names): %s",
+ NameListToString(names))));
+ break;
+ }
+
+ *nspname_p = schemaname;
+ *objname_p = objname;
+}
+
+/*
+ * LookupNamespaceNoError
+ * Look up a schema name.
+ *
+ * Returns the namespace OID, or InvalidOid if not found.
+ *
+ * Note this does NOT perform any permissions check --- callers are
+ * responsible for being sure that an appropriate check is made.
+ * In the majority of cases LookupExplicitNamespace is preferable.
+ */
+Oid
+LookupNamespaceNoError(const char *nspname)
+{
+ /* check for pg_temp alias */
+ if (strcmp(nspname, "pg_temp") == 0)
+ {
+ if (OidIsValid(myTempNamespace))
+ {
+ InvokeNamespaceSearchHook(myTempNamespace, true);
+ return myTempNamespace;
+ }
+
+ /*
+ * Since this is used only for looking up existing objects, there is
+ * no point in trying to initialize the temp namespace here; and doing
+ * so might create problems for some callers. Just report "not found".
+ */
+ return InvalidOid;
+ }
+
+ return get_namespace_oid(nspname, true);
+}
+
+/*
+ * LookupExplicitNamespace
+ * Process an explicitly-specified schema name: look up the schema
+ * and verify we have USAGE (lookup) rights in it.
+ *
+ * Returns the namespace OID
+ */
+Oid
+LookupExplicitNamespace(const char *nspname, bool missing_ok)
+{
+ Oid namespaceId;
+ AclResult aclresult;
+
+ /* check for pg_temp alias */
+ if (strcmp(nspname, "pg_temp") == 0)
+ {
+ if (OidIsValid(myTempNamespace))
+ return myTempNamespace;
+
+ /*
+ * Since this is used only for looking up existing objects, there is
+ * no point in trying to initialize the temp namespace here; and doing
+ * so might create problems for some callers --- just fall through.
+ */
+ }
+
+ namespaceId = get_namespace_oid(nspname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ return InvalidOid;
+
+ aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, OBJECT_SCHEMA,
+ nspname);
+ /* Schema search hook for this lookup */
+ InvokeNamespaceSearchHook(namespaceId, true);
+
+ return namespaceId;
+}
+
+/*
+ * LookupCreationNamespace
+ * Look up the schema and verify we have CREATE rights on it.
+ *
+ * This is just like LookupExplicitNamespace except for the different
+ * permission check, and that we are willing to create pg_temp if needed.
+ *
+ * Note: calling this may result in a CommandCounterIncrement operation,
+ * if we have to create or clean out the temp namespace.
+ */
+Oid
+LookupCreationNamespace(const char *nspname)
+{
+ Oid namespaceId;
+ AclResult aclresult;
+
+ /* check for pg_temp alias */
+ if (strcmp(nspname, "pg_temp") == 0)
+ {
+ /* Initialize temp namespace */
+ AccessTempTableNamespace(false);
+ return myTempNamespace;
+ }
+
+ namespaceId = get_namespace_oid(nspname, false);
+
+ aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, OBJECT_SCHEMA,
+ nspname);
+
+ return namespaceId;
+}
+
+/*
+ * Common checks on switching namespaces.
+ *
+ * We complain if either the old or new namespaces is a temporary schema
+ * (or temporary toast schema), or if either the old or new namespaces is the
+ * TOAST schema.
+ */
+void
+CheckSetNamespace(Oid oldNspOid, Oid nspOid)
+{
+ /* disallow renaming into or out of temp schemas */
+ if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot move objects into or out of temporary schemas")));
+
+ /* same for TOAST schema */
+ if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot move objects into or out of TOAST schema")));
+}
+
+/*
+ * QualifiedNameGetCreationNamespace
+ * Given a possibly-qualified name for an object (in List-of-Values
+ * format), determine what namespace the object should be created in.
+ * Also extract and return the object name (last component of list).
+ *
+ * Note: this does not apply any permissions check. Callers must check
+ * for CREATE rights on the selected namespace when appropriate.
+ *
+ * Note: calling this may result in a CommandCounterIncrement operation,
+ * if we have to create or clean out the temp namespace.
+ */
+Oid
+QualifiedNameGetCreationNamespace(List *names, char **objname_p)
+{
+ char *schemaname;
+ Oid namespaceId;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(names, &schemaname, objname_p);
+
+ if (schemaname)
+ {
+ /* check for pg_temp alias */
+ if (strcmp(schemaname, "pg_temp") == 0)
+ {
+ /* Initialize temp namespace */
+ AccessTempTableNamespace(false);
+ return myTempNamespace;
+ }
+ /* use exact schema given */
+ namespaceId = get_namespace_oid(schemaname, false);
+ /* we do not check for USAGE rights here! */
+ }
+ else
+ {
+ /* use the default creation namespace */
+ recomputeNamespacePath();
+ if (activeTempCreationPending)
+ {
+ /* Need to initialize temp namespace */
+ AccessTempTableNamespace(true);
+ return myTempNamespace;
+ }
+ namespaceId = activeCreationNamespace;
+ if (!OidIsValid(namespaceId))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_SCHEMA),
+ errmsg("no schema has been selected to create in")));
+ }
+
+ return namespaceId;
+}
+
+/*
+ * get_namespace_oid - given a namespace name, look up the OID
+ *
+ * If missing_ok is false, throw an error if namespace name not found. If
+ * true, just return InvalidOid.
+ */
+Oid
+get_namespace_oid(const char *nspname, bool missing_ok)
+{
+ Oid oid;
+
+ oid = GetSysCacheOid1(NAMESPACENAME, Anum_pg_namespace_oid,
+ CStringGetDatum(nspname));
+ if (!OidIsValid(oid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_SCHEMA),
+ errmsg("schema \"%s\" does not exist", nspname)));
+
+ return oid;
+}
+
+/*
+ * makeRangeVarFromNameList
+ * Utility routine to convert a qualified-name list into RangeVar form.
+ */
+RangeVar *
+makeRangeVarFromNameList(List *names)
+{
+ RangeVar *rel = makeRangeVar(NULL, NULL, -1);
+
+ switch (list_length(names))
+ {
+ case 1:
+ rel->relname = strVal(linitial(names));
+ break;
+ case 2:
+ rel->schemaname = strVal(linitial(names));
+ rel->relname = strVal(lsecond(names));
+ break;
+ case 3:
+ rel->catalogname = strVal(linitial(names));
+ rel->schemaname = strVal(lsecond(names));
+ rel->relname = strVal(lthird(names));
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("improper relation name (too many dotted names): %s",
+ NameListToString(names))));
+ break;
+ }
+
+ return rel;
+}
+
+/*
+ * NameListToString
+ * Utility routine to convert a qualified-name list into a string.
+ *
+ * This is used primarily to form error messages, and so we do not quote
+ * the list elements, for the sake of legibility.
+ *
+ * In most scenarios the list elements should always be Value strings,
+ * but we also allow A_Star for the convenience of ColumnRef processing.
+ */
+char *
+NameListToString(List *names)
+{
+ StringInfoData string;
+ ListCell *l;
+
+ initStringInfo(&string);
+
+ foreach(l, names)
+ {
+ Node *name = (Node *) lfirst(l);
+
+ if (l != list_head(names))
+ appendStringInfoChar(&string, '.');
+
+ if (IsA(name, String))
+ appendStringInfoString(&string, strVal(name));
+ else if (IsA(name, A_Star))
+ appendStringInfoChar(&string, '*');
+ else
+ elog(ERROR, "unexpected node type in name list: %d",
+ (int) nodeTag(name));
+ }
+
+ return string.data;
+}
+
+/*
+ * NameListToQuotedString
+ * Utility routine to convert a qualified-name list into a string.
+ *
+ * Same as above except that names will be double-quoted where necessary,
+ * so the string could be re-parsed (eg, by textToQualifiedNameList).
+ */
+char *
+NameListToQuotedString(List *names)
+{
+ StringInfoData string;
+ ListCell *l;
+
+ initStringInfo(&string);
+
+ foreach(l, names)
+ {
+ if (l != list_head(names))
+ appendStringInfoChar(&string, '.');
+ appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
+ }
+
+ return string.data;
+}
+
+/*
+ * isTempNamespace - is the given namespace my temporary-table namespace?
+ */
+bool
+isTempNamespace(Oid namespaceId)
+{
+ if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
+ return true;
+ return false;
+}
+
+/*
+ * isTempToastNamespace - is the given namespace my temporary-toast-table
+ * namespace?
+ */
+bool
+isTempToastNamespace(Oid namespaceId)
+{
+ if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
+ return true;
+ return false;
+}
+
+/*
+ * isTempOrTempToastNamespace - is the given namespace my temporary-table
+ * namespace or my temporary-toast-table namespace?
+ */
+bool
+isTempOrTempToastNamespace(Oid namespaceId)
+{
+ if (OidIsValid(myTempNamespace) &&
+ (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
+ return true;
+ return false;
+}
+
+/*
+ * isAnyTempNamespace - is the given namespace a temporary-table namespace
+ * (either my own, or another backend's)? Temporary-toast-table namespaces
+ * are included, too.
+ */
+bool
+isAnyTempNamespace(Oid namespaceId)
+{
+ bool result;
+ char *nspname;
+
+ /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
+ nspname = get_namespace_name(namespaceId);
+ if (!nspname)
+ return false; /* no such namespace? */
+ result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
+ (strncmp(nspname, "pg_toast_temp_", 14) == 0);
+ pfree(nspname);
+ return result;
+}
+
+/*
+ * isOtherTempNamespace - is the given namespace some other backend's
+ * temporary-table namespace (including temporary-toast-table namespaces)?
+ *
+ * Note: for most purposes in the C code, this function is obsolete. Use
+ * RELATION_IS_OTHER_TEMP() instead to detect non-local temp relations.
+ */
+bool
+isOtherTempNamespace(Oid namespaceId)
+{
+ /* If it's my own temp namespace, say "false" */
+ if (isTempOrTempToastNamespace(namespaceId))
+ return false;
+ /* Else, if it's any temp namespace, say "true" */
+ return isAnyTempNamespace(namespaceId);
+}
+
+/*
+ * checkTempNamespaceStatus - is the given namespace owned and actively used
+ * by a backend?
+ *
+ * Note: this can be used while scanning relations in pg_class to detect
+ * orphaned temporary tables or namespaces with a backend connected to a
+ * given database. The result may be out of date quickly, so the caller
+ * must be careful how to handle this information.
+ */
+TempNamespaceStatus
+checkTempNamespaceStatus(Oid namespaceId)
+{
+ PGPROC *proc;
+ int backendId;
+
+ Assert(OidIsValid(MyDatabaseId));
+
+ backendId = GetTempNamespaceBackendId(namespaceId);
+
+ /* No such namespace, or its name shows it's not temp? */
+ if (backendId == InvalidBackendId)
+ return TEMP_NAMESPACE_NOT_TEMP;
+
+ /* Is the backend alive? */
+ proc = BackendIdGetProc(backendId);
+ if (proc == NULL)
+ return TEMP_NAMESPACE_IDLE;
+
+ /* Is the backend connected to the same database we are looking at? */
+ if (proc->databaseId != MyDatabaseId)
+ return TEMP_NAMESPACE_IDLE;
+
+ /* Does the backend own the temporary namespace? */
+ if (proc->tempNamespaceId != namespaceId)
+ return TEMP_NAMESPACE_IDLE;
+
+ /* Yup, so namespace is busy */
+ return TEMP_NAMESPACE_IN_USE;
+}
+
+/*
+ * GetTempNamespaceBackendId - if the given namespace is a temporary-table
+ * namespace (either my own, or another backend's), return the BackendId
+ * that owns it. Temporary-toast-table namespaces are included, too.
+ * If it isn't a temp namespace, return InvalidBackendId.
+ */
+int
+GetTempNamespaceBackendId(Oid namespaceId)
+{
+ int result;
+ char *nspname;
+
+ /* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
+ nspname = get_namespace_name(namespaceId);
+ if (!nspname)
+ return InvalidBackendId; /* no such namespace? */
+ if (strncmp(nspname, "pg_temp_", 8) == 0)
+ result = atoi(nspname + 8);
+ else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
+ result = atoi(nspname + 14);
+ else
+ result = InvalidBackendId;
+ pfree(nspname);
+ return result;
+}
+
+/*
+ * GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
+ * which must already be assigned. (This is only used when creating a toast
+ * table for a temp table, so we must have already done InitTempTableNamespace)
+ */
+Oid
+GetTempToastNamespace(void)
+{
+ Assert(OidIsValid(myTempToastNamespace));
+ return myTempToastNamespace;
+}
+
+
+/*
+ * GetTempNamespaceState - fetch status of session's temporary namespace
+ *
+ * This is used for conveying state to a parallel worker, and is not meant
+ * for general-purpose access.
+ */
+void
+GetTempNamespaceState(Oid *tempNamespaceId, Oid *tempToastNamespaceId)
+{
+ /* Return namespace OIDs, or 0 if session has not created temp namespace */
+ *tempNamespaceId = myTempNamespace;
+ *tempToastNamespaceId = myTempToastNamespace;
+}
+
+/*
+ * SetTempNamespaceState - set status of session's temporary namespace
+ *
+ * This is used for conveying state to a parallel worker, and is not meant for
+ * general-purpose access. By transferring these namespace OIDs to workers,
+ * we ensure they will have the same notion of the search path as their leader
+ * does.
+ */
+void
+SetTempNamespaceState(Oid tempNamespaceId, Oid tempToastNamespaceId)
+{
+ /* Worker should not have created its own namespaces ... */
+ Assert(myTempNamespace == InvalidOid);
+ Assert(myTempToastNamespace == InvalidOid);
+ Assert(myTempNamespaceSubID == InvalidSubTransactionId);
+
+ /* Assign same namespace OIDs that leader has */
+ myTempNamespace = tempNamespaceId;
+ myTempToastNamespace = tempToastNamespaceId;
+
+ /*
+ * It's fine to leave myTempNamespaceSubID == InvalidSubTransactionId.
+ * Even if the namespace is new so far as the leader is concerned, it's
+ * not new to the worker, and we certainly wouldn't want the worker trying
+ * to destroy it.
+ */
+
+ baseSearchPathValid = false; /* may need to rebuild list */
+}
+
+
+/*
+ * GetOverrideSearchPath - fetch current search path definition in form
+ * used by PushOverrideSearchPath.
+ *
+ * The result structure is allocated in the specified memory context
+ * (which might or might not be equal to CurrentMemoryContext); but any
+ * junk created by revalidation calculations will be in CurrentMemoryContext.
+ */
+OverrideSearchPath *
+GetOverrideSearchPath(MemoryContext context)
+{
+ OverrideSearchPath *result;
+ List *schemas;
+ MemoryContext oldcxt;
+
+ recomputeNamespacePath();
+
+ oldcxt = MemoryContextSwitchTo(context);
+
+ result = (OverrideSearchPath *) palloc0(sizeof(OverrideSearchPath));
+ schemas = list_copy(activeSearchPath);
+ while (schemas && linitial_oid(schemas) != activeCreationNamespace)
+ {
+ if (linitial_oid(schemas) == myTempNamespace)
+ result->addTemp = true;
+ else
+ {
+ Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
+ result->addCatalog = true;
+ }
+ schemas = list_delete_first(schemas);
+ }
+ result->schemas = schemas;
+ result->generation = activePathGeneration;
+
+ MemoryContextSwitchTo(oldcxt);
+
+ return result;
+}
+
+/*
+ * CopyOverrideSearchPath - copy the specified OverrideSearchPath.
+ *
+ * The result structure is allocated in CurrentMemoryContext.
+ */
+OverrideSearchPath *
+CopyOverrideSearchPath(OverrideSearchPath *path)
+{
+ OverrideSearchPath *result;
+
+ result = (OverrideSearchPath *) palloc(sizeof(OverrideSearchPath));
+ result->schemas = list_copy(path->schemas);
+ result->addCatalog = path->addCatalog;
+ result->addTemp = path->addTemp;
+ result->generation = path->generation;
+
+ return result;
+}
+
+/*
+ * OverrideSearchPathMatchesCurrent - does path match current setting?
+ *
+ * This is tested over and over in some common code paths, and in the typical
+ * scenario where the active search path seldom changes, it'll always succeed.
+ * We make that case fast by keeping a generation counter that is advanced
+ * whenever the active search path changes.
+ */
+bool
+OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
+{
+ ListCell *lc,
+ *lcp;
+
+ recomputeNamespacePath();
+
+ /* Quick out if already known equal to active path. */
+ if (path->generation == activePathGeneration)
+ return true;
+
+ /* We scan down the activeSearchPath to see if it matches the input. */
+ lc = list_head(activeSearchPath);
+
+ /* If path->addTemp, first item should be my temp namespace. */
+ if (path->addTemp)
+ {
+ if (lc && lfirst_oid(lc) == myTempNamespace)
+ lc = lnext(activeSearchPath, lc);
+ else
+ return false;
+ }
+ /* If path->addCatalog, next item should be pg_catalog. */
+ if (path->addCatalog)
+ {
+ if (lc && lfirst_oid(lc) == PG_CATALOG_NAMESPACE)
+ lc = lnext(activeSearchPath, lc);
+ else
+ return false;
+ }
+ /* We should now be looking at the activeCreationNamespace. */
+ if (activeCreationNamespace != (lc ? lfirst_oid(lc) : InvalidOid))
+ return false;
+ /* The remainder of activeSearchPath should match path->schemas. */
+ foreach(lcp, path->schemas)
+ {
+ if (lc && lfirst_oid(lc) == lfirst_oid(lcp))
+ lc = lnext(activeSearchPath, lc);
+ else
+ return false;
+ }
+ if (lc)
+ return false;
+
+ /*
+ * Update path->generation so that future tests will return quickly, so
+ * long as the active search path doesn't change.
+ */
+ path->generation = activePathGeneration;
+
+ return true;
+}
+
+/*
+ * PushOverrideSearchPath - temporarily override the search path
+ *
+ * We allow nested overrides, hence the push/pop terminology. The GUC
+ * search_path variable is ignored while an override is active.
+ *
+ * It's possible that newpath->useTemp is set but there is no longer any
+ * active temp namespace, if the path was saved during a transaction that
+ * created a temp namespace and was later rolled back. In that case we just
+ * ignore useTemp. A plausible alternative would be to create a new temp
+ * namespace, but for existing callers that's not necessary because an empty
+ * temp namespace wouldn't affect their results anyway.
+ *
+ * It's also worth noting that other schemas listed in newpath might not
+ * exist anymore either. We don't worry about this because OIDs that match
+ * no existing namespace will simply not produce any hits during searches.
+ */
+void
+PushOverrideSearchPath(OverrideSearchPath *newpath)
+{
+ OverrideStackEntry *entry;
+ List *oidlist;
+ Oid firstNS;
+ MemoryContext oldcxt;
+
+ /*
+ * Copy the list for safekeeping, and insert implicitly-searched
+ * namespaces as needed. This code should track recomputeNamespacePath.
+ */
+ oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+
+ oidlist = list_copy(newpath->schemas);
+
+ /*
+ * Remember the first member of the explicit list.
+ */
+ if (oidlist == NIL)
+ firstNS = InvalidOid;
+ else
+ firstNS = linitial_oid(oidlist);
+
+ /*
+ * Add any implicitly-searched namespaces to the list. Note these go on
+ * the front, not the back; also notice that we do not check USAGE
+ * permissions for these.
+ */
+ if (newpath->addCatalog)
+ oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
+
+ if (newpath->addTemp && OidIsValid(myTempNamespace))
+ oidlist = lcons_oid(myTempNamespace, oidlist);
+
+ /*
+ * Build the new stack entry, then insert it at the head of the list.
+ */
+ entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
+ entry->searchPath = oidlist;
+ entry->creationNamespace = firstNS;
+ entry->nestLevel = GetCurrentTransactionNestLevel();
+
+ overrideStack = lcons(entry, overrideStack);
+
+ /* And make it active. */
+ activeSearchPath = entry->searchPath;
+ activeCreationNamespace = entry->creationNamespace;
+ activeTempCreationPending = false; /* XXX is this OK? */
+
+ /*
+ * We always increment activePathGeneration when pushing/popping an
+ * override path. In current usage, these actions always change the
+ * effective path state, so there's no value in checking to see if it
+ * didn't change.
+ */
+ activePathGeneration++;
+
+ MemoryContextSwitchTo(oldcxt);
+}
+
+/*
+ * PopOverrideSearchPath - undo a previous PushOverrideSearchPath
+ *
+ * Any push during a (sub)transaction will be popped automatically at abort.
+ * But it's caller error if a push isn't popped in normal control flow.
+ */
+void
+PopOverrideSearchPath(void)
+{
+ OverrideStackEntry *entry;
+
+ /* Sanity checks. */
+ if (overrideStack == NIL)
+ elog(ERROR, "bogus PopOverrideSearchPath call");
+ entry = (OverrideStackEntry *) linitial(overrideStack);
+ if (entry->nestLevel != GetCurrentTransactionNestLevel())
+ elog(ERROR, "bogus PopOverrideSearchPath call");
+
+ /* Pop the stack and free storage. */
+ overrideStack = list_delete_first(overrideStack);
+ list_free(entry->searchPath);
+ pfree(entry);
+
+ /* Activate the next level down. */
+ if (overrideStack)
+ {
+ entry = (OverrideStackEntry *) linitial(overrideStack);
+ activeSearchPath = entry->searchPath;
+ activeCreationNamespace = entry->creationNamespace;
+ activeTempCreationPending = false; /* XXX is this OK? */
+ }
+ else
+ {
+ /* If not baseSearchPathValid, this is useless but harmless */
+ activeSearchPath = baseSearchPath;
+ activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
+ }
+
+ /* As above, the generation always increments. */
+ activePathGeneration++;
+}
+
+
+/*
+ * get_collation_oid - find a collation by possibly qualified name
+ *
+ * Note that this will only find collations that work with the current
+ * database's encoding.
+ */
+Oid
+get_collation_oid(List *name, bool missing_ok)
+{
+ char *schemaname;
+ char *collation_name;
+ int32 dbencoding = GetDatabaseEncoding();
+ Oid namespaceId;
+ Oid colloid;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(name, &schemaname, &collation_name);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ return InvalidOid;
+
+ colloid = lookup_collation(collation_name, namespaceId, dbencoding);
+ if (OidIsValid(colloid))
+ return colloid;
+ }
+ else
+ {
+ /* search for it in search path */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ colloid = lookup_collation(collation_name, namespaceId, dbencoding);
+ if (OidIsValid(colloid))
+ return colloid;
+ }
+ }
+
+ /* Not found in path */
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("collation \"%s\" for encoding \"%s\" does not exist",
+ NameListToString(name), GetDatabaseEncodingName())));
+ return InvalidOid;
+}
+
+/*
+ * get_conversion_oid - find a conversion by possibly qualified name
+ */
+Oid
+get_conversion_oid(List *name, bool missing_ok)
+{
+ char *schemaname;
+ char *conversion_name;
+ Oid namespaceId;
+ Oid conoid = InvalidOid;
+ ListCell *l;
+
+ /* deconstruct the name list */
+ DeconstructQualifiedName(name, &schemaname, &conversion_name);
+
+ if (schemaname)
+ {
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
+ if (missing_ok && !OidIsValid(namespaceId))
+ conoid = InvalidOid;
+ else
+ conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
+ PointerGetDatum(conversion_name),
+ ObjectIdGetDatum(namespaceId));
+ }
+ else
+ {
+ /* search for it in search path */
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ conoid = GetSysCacheOid2(CONNAMENSP, Anum_pg_conversion_oid,
+ PointerGetDatum(conversion_name),
+ ObjectIdGetDatum(namespaceId));
+ if (OidIsValid(conoid))
+ return conoid;
+ }
+ }
+
+ /* Not found in path */
+ if (!OidIsValid(conoid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("conversion \"%s\" does not exist",
+ NameListToString(name))));
+ return conoid;
+}
+
+/*
+ * FindDefaultConversionProc - find default encoding conversion proc
+ */
+Oid
+FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
+{
+ Oid proc;
+ ListCell *l;
+
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not look in temp namespace */
+
+ proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
+ if (OidIsValid(proc))
+ return proc;
+ }
+
+ /* Not found in path */
+ return InvalidOid;
+}
+
+/*
+ * recomputeNamespacePath - recompute path derived variables if needed.
+ */
+static void
+recomputeNamespacePath(void)
+{
+ Oid roleid = GetUserId();
+ char *rawname;
+ List *namelist;
+ List *oidlist;
+ List *newpath;
+ ListCell *l;
+ bool temp_missing;
+ Oid firstNS;
+ bool pathChanged;
+ MemoryContext oldcxt;
+
+ /* Do nothing if an override search spec is active. */
+ if (overrideStack)
+ return;
+
+ /* Do nothing if path is already valid. */
+ if (baseSearchPathValid && namespaceUser == roleid)
+ return;
+
+ /* Need a modifiable copy of namespace_search_path string */
+ rawname = pstrdup(namespace_search_path);
+
+ /* Parse string into list of identifiers */
+ if (!SplitIdentifierString(rawname, ',', &namelist))
+ {
+ /* syntax error in name list */
+ /* this should not happen if GUC checked check_search_path */
+ elog(ERROR, "invalid list syntax");
+ }
+
+ /*
+ * Convert the list of names to a list of OIDs. If any names are not
+ * recognizable or we don't have read access, just leave them out of the
+ * list. (We can't raise an error, since the search_path setting has
+ * already been accepted.) Don't make duplicate entries, either.
+ */
+ oidlist = NIL;
+ temp_missing = false;
+ foreach(l, namelist)
+ {
+ char *curname = (char *) lfirst(l);
+ Oid namespaceId;
+
+ if (strcmp(curname, "$user") == 0)
+ {
+ /* $user --- substitute namespace matching user name, if any */
+ HeapTuple tuple;
+
+ tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
+ if (HeapTupleIsValid(tuple))
+ {
+ char *rname;
+
+ rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
+ namespaceId = get_namespace_oid(rname, true);
+ ReleaseSysCache(tuple);
+ if (OidIsValid(namespaceId) &&
+ !list_member_oid(oidlist, namespaceId) &&
+ pg_namespace_aclcheck(namespaceId, roleid,
+ ACL_USAGE) == ACLCHECK_OK &&
+ InvokeNamespaceSearchHook(namespaceId, false))
+ oidlist = lappend_oid(oidlist, namespaceId);
+ }
+ }
+ else if (strcmp(curname, "pg_temp") == 0)
+ {
+ /* pg_temp --- substitute temp namespace, if any */
+ if (OidIsValid(myTempNamespace))
+ {
+ if (!list_member_oid(oidlist, myTempNamespace) &&
+ InvokeNamespaceSearchHook(myTempNamespace, false))
+ oidlist = lappend_oid(oidlist, myTempNamespace);
+ }
+ else
+ {
+ /* If it ought to be the creation namespace, set flag */
+ if (oidlist == NIL)
+ temp_missing = true;
+ }
+ }
+ else
+ {
+ /* normal namespace reference */
+ namespaceId = get_namespace_oid(curname, true);
+ if (OidIsValid(namespaceId) &&
+ !list_member_oid(oidlist, namespaceId) &&
+ pg_namespace_aclcheck(namespaceId, roleid,
+ ACL_USAGE) == ACLCHECK_OK &&
+ InvokeNamespaceSearchHook(namespaceId, false))
+ oidlist = lappend_oid(oidlist, namespaceId);
+ }
+ }
+
+ /*
+ * Remember the first member of the explicit list. (Note: this is
+ * nominally wrong if temp_missing, but we need it anyway to distinguish
+ * explicit from implicit mention of pg_catalog.)
+ */
+ if (oidlist == NIL)
+ firstNS = InvalidOid;
+ else
+ firstNS = linitial_oid(oidlist);
+
+ /*
+ * Add any implicitly-searched namespaces to the list. Note these go on
+ * the front, not the back; also notice that we do not check USAGE
+ * permissions for these.
+ */
+ if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
+ oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
+
+ if (OidIsValid(myTempNamespace) &&
+ !list_member_oid(oidlist, myTempNamespace))
+ oidlist = lcons_oid(myTempNamespace, oidlist);
+
+ /*
+ * We want to detect the case where the effective value of the base search
+ * path variables didn't change. As long as we're doing so, we can avoid
+ * copying the OID list unncessarily.
+ */
+ if (baseCreationNamespace == firstNS &&
+ baseTempCreationPending == temp_missing &&
+ equal(oidlist, baseSearchPath))
+ {
+ pathChanged = false;
+ }
+ else
+ {
+ pathChanged = true;
+
+ /* Must save OID list in permanent storage. */
+ oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+ newpath = list_copy(oidlist);
+ MemoryContextSwitchTo(oldcxt);
+
+ /* Now safe to assign to state variables. */
+ list_free(baseSearchPath);
+ baseSearchPath = newpath;
+ baseCreationNamespace = firstNS;
+ baseTempCreationPending = temp_missing;
+ }
+
+ /* Mark the path valid. */
+ baseSearchPathValid = true;
+ namespaceUser = roleid;
+
+ /* And make it active. */
+ activeSearchPath = baseSearchPath;
+ activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
+
+ /*
+ * Bump the generation only if something actually changed. (Notice that
+ * what we compared to was the old state of the base path variables; so
+ * this does not deal with the situation where we have just popped an
+ * override path and restored the prior state of the base path. Instead
+ * we rely on the override-popping logic to have bumped the generation.)
+ */
+ if (pathChanged)
+ activePathGeneration++;
+
+ /* Clean up. */
+ pfree(rawname);
+ list_free(namelist);
+ list_free(oidlist);
+}
+
+/*
+ * AccessTempTableNamespace
+ * Provide access to a temporary namespace, potentially creating it
+ * if not present yet. This routine registers if the namespace gets
+ * in use in this transaction. 'force' can be set to true to allow
+ * the caller to enforce the creation of the temporary namespace for
+ * use in this backend, which happens if its creation is pending.
+ */
+static void
+AccessTempTableNamespace(bool force)
+{
+ /*
+ * Make note that this temporary namespace has been accessed in this
+ * transaction.
+ */
+ MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
+
+ /*
+ * If the caller attempting to access a temporary schema expects the
+ * creation of the namespace to be pending and should be enforced, then go
+ * through the creation.
+ */
+ if (!force && OidIsValid(myTempNamespace))
+ return;
+
+ /*
+ * The temporary tablespace does not exist yet and is wanted, so
+ * initialize it.
+ */
+ InitTempTableNamespace();
+}
+
+/*
+ * InitTempTableNamespace
+ * Initialize temp table namespace on first use in a particular backend
+ */
+static void
+InitTempTableNamespace(void)
+{
+ char namespaceName[NAMEDATALEN];
+ Oid namespaceId;
+ Oid toastspaceId;
+
+ Assert(!OidIsValid(myTempNamespace));
+
+ /*
+ * First, do permission check to see if we are authorized to make temp
+ * tables. We use a nonstandard error message here since "databasename:
+ * permission denied" might be a tad cryptic.
+ *
+ * Note that ACL_CREATE_TEMP rights are rechecked in pg_namespace_aclmask;
+ * that's necessary since current user ID could change during the session.
+ * But there's no need to make the namespace in the first place until a
+ * temp table creation request is made by someone with appropriate rights.
+ */
+ if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
+ ACL_CREATE_TEMP) != ACLCHECK_OK)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied to create temporary tables in database \"%s\"",
+ get_database_name(MyDatabaseId))));
+
+ /*
+ * Do not allow a Hot Standby session to make temp tables. Aside from
+ * problems with modifying the system catalogs, there is a naming
+ * conflict: pg_temp_N belongs to the session with BackendId N on the
+ * master, not to a hot standby session with the same BackendId. We
+ * should not be able to get here anyway due to XactReadOnly checks, but
+ * let's just make real sure. Note that this also backstops various
+ * operations that allow XactReadOnly transactions to modify temp tables;
+ * they'd need RecoveryInProgress checks if not for this.
+ */
+ if (RecoveryInProgress())
+ ereport(ERROR,
+ (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
+ errmsg("cannot create temporary tables during recovery")));
+
+ /* Parallel workers can't create temporary tables, either. */
+ if (IsParallelWorker())
+ ereport(ERROR,
+ (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
+ errmsg("cannot create temporary tables during a parallel operation")));
+
+ snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
+
+ namespaceId = get_namespace_oid(namespaceName, true);
+ if (!OidIsValid(namespaceId))
+ {
+ /*
+ * First use of this temp namespace in this database; create it. The
+ * temp namespaces are always owned by the superuser. We leave their
+ * permissions at default --- i.e., no access except to superuser ---
+ * to ensure that unprivileged users can't peek at other backends'
+ * temp tables. This works because the places that access the temp
+ * namespace for my own backend skip permissions checks on it.
+ */
+ namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
+ true);
+ /* Advance command counter to make namespace visible */
+ CommandCounterIncrement();
+ }
+ else
+ {
+ /*
+ * If the namespace already exists, clean it out (in case the former
+ * owner crashed without doing so).
+ */
+ RemoveTempRelations(namespaceId);
+ }
+
+ /*
+ * If the corresponding toast-table namespace doesn't exist yet, create
+ * it. (We assume there is no need to clean it out if it does exist, since
+ * dropping a parent table should make its toast table go away.)
+ */
+ snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
+ MyBackendId);
+
+ toastspaceId = get_namespace_oid(namespaceName, true);
+ if (!OidIsValid(toastspaceId))
+ {
+ toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
+ true);
+ /* Advance command counter to make namespace visible */
+ CommandCounterIncrement();
+ }
+
+ /*
+ * Okay, we've prepared the temp namespace ... but it's not committed yet,
+ * so all our work could be undone by transaction rollback. Set flag for
+ * AtEOXact_Namespace to know what to do.
+ */
+ myTempNamespace = namespaceId;
+ myTempToastNamespace = toastspaceId;
+
+ /*
+ * Mark MyProc as owning this namespace which other processes can use to
+ * decide if a temporary namespace is in use or not. We assume that
+ * assignment of namespaceId is an atomic operation. Even if it is not,
+ * the temporary relation which resulted in the creation of this temporary
+ * namespace is still locked until the current transaction commits, and
+ * its pg_namespace row is not visible yet. However it does not matter:
+ * this flag makes the namespace as being in use, so no objects created on
+ * it would be removed concurrently.
+ */
+ MyProc->tempNamespaceId = namespaceId;
+
+ /* It should not be done already. */
+ AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
+ myTempNamespaceSubID = GetCurrentSubTransactionId();
+
+ baseSearchPathValid = false; /* need to rebuild list */
+}
+
+/*
+ * End-of-transaction cleanup for namespaces.
+ */
+void
+AtEOXact_Namespace(bool isCommit, bool parallel)
+{
+ /*
+ * If we abort the transaction in which a temp namespace was selected,
+ * we'll have to do any creation or cleanout work over again. So, just
+ * forget the namespace entirely until next time. On the other hand, if
+ * we commit then register an exit callback to clean out the temp tables
+ * at backend shutdown. (We only want to register the callback once per
+ * session, so this is a good place to do it.)
+ */
+ if (myTempNamespaceSubID != InvalidSubTransactionId && !parallel)
+ {
+ if (isCommit)
+ before_shmem_exit(RemoveTempRelationsCallback, 0);
+ else
+ {
+ myTempNamespace = InvalidOid;
+ myTempToastNamespace = InvalidOid;
+ baseSearchPathValid = false; /* need to rebuild list */
+
+ /*
+ * Reset the temporary namespace flag in MyProc. We assume that
+ * this operation is atomic.
+ *
+ * Because this transaction is aborting, the pg_namespace row is
+ * not visible to anyone else anyway, but that doesn't matter:
+ * it's not a problem if objects contained in this namespace are
+ * removed concurrently.
+ */
+ MyProc->tempNamespaceId = InvalidOid;
+ }
+ myTempNamespaceSubID = InvalidSubTransactionId;
+ }
+
+ /*
+ * Clean up if someone failed to do PopOverrideSearchPath
+ */
+ if (overrideStack)
+ {
+ if (isCommit)
+ elog(WARNING, "leaked override search path");
+ while (overrideStack)
+ {
+ OverrideStackEntry *entry;
+
+ entry = (OverrideStackEntry *) linitial(overrideStack);
+ overrideStack = list_delete_first(overrideStack);
+ list_free(entry->searchPath);
+ pfree(entry);
+ }
+ /* If not baseSearchPathValid, this is useless but harmless */
+ activeSearchPath = baseSearchPath;
+ activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
+ /* Always bump generation --- see note in recomputeNamespacePath */
+ activePathGeneration++;
+ }
+}
+
+/*
+ * AtEOSubXact_Namespace
+ *
+ * At subtransaction commit, propagate the temp-namespace-creation
+ * flag to the parent subtransaction.
+ *
+ * At subtransaction abort, forget the flag if we set it up.
+ */
+void
+AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
+ SubTransactionId parentSubid)
+{
+ OverrideStackEntry *entry;
+
+ if (myTempNamespaceSubID == mySubid)
+ {
+ if (isCommit)
+ myTempNamespaceSubID = parentSubid;
+ else
+ {
+ myTempNamespaceSubID = InvalidSubTransactionId;
+ /* TEMP namespace creation failed, so reset state */
+ myTempNamespace = InvalidOid;
+ myTempToastNamespace = InvalidOid;
+ baseSearchPathValid = false; /* need to rebuild list */
+
+ /*
+ * Reset the temporary namespace flag in MyProc. We assume that
+ * this operation is atomic.
+ *
+ * Because this subtransaction is aborting, the pg_namespace row
+ * is not visible to anyone else anyway, but that doesn't matter:
+ * it's not a problem if objects contained in this namespace are
+ * removed concurrently.
+ */
+ MyProc->tempNamespaceId = InvalidOid;
+ }
+ }
+
+ /*
+ * Clean up if someone failed to do PopOverrideSearchPath
+ */
+ while (overrideStack)
+ {
+ entry = (OverrideStackEntry *) linitial(overrideStack);
+ if (entry->nestLevel < GetCurrentTransactionNestLevel())
+ break;
+ if (isCommit)
+ elog(WARNING, "leaked override search path");
+ overrideStack = list_delete_first(overrideStack);
+ list_free(entry->searchPath);
+ pfree(entry);
+ /* Always bump generation --- see note in recomputeNamespacePath */
+ activePathGeneration++;
+ }
+
+ /* Activate the next level down. */
+ if (overrideStack)
+ {
+ entry = (OverrideStackEntry *) linitial(overrideStack);
+ activeSearchPath = entry->searchPath;
+ activeCreationNamespace = entry->creationNamespace;
+ activeTempCreationPending = false; /* XXX is this OK? */
+
+ /*
+ * It's probably unnecessary to bump generation here, but this should
+ * not be a performance-critical case, so better to be over-cautious.
+ */
+ activePathGeneration++;
+ }
+ else
+ {
+ /* If not baseSearchPathValid, this is useless but harmless */
+ activeSearchPath = baseSearchPath;
+ activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
+
+ /*
+ * If we popped an override stack entry, then we already bumped the
+ * generation above. If we did not, then the above assignments did
+ * nothing and we need not bump the generation.
+ */
+ }
+}
+
+/*
+ * Remove all relations in the specified temp namespace.
+ *
+ * This is called at backend shutdown (if we made any temp relations).
+ * It is also called when we begin using a pre-existing temp namespace,
+ * in order to clean out any relations that might have been created by
+ * a crashed backend.
+ */
+static void
+RemoveTempRelations(Oid tempNamespaceId)
+{
+ ObjectAddress object;
+
+ /*
+ * We want to get rid of everything in the target namespace, but not the
+ * namespace itself (deleting it only to recreate it later would be a
+ * waste of cycles). Hence, specify SKIP_ORIGINAL. It's also an INTERNAL
+ * deletion, and we want to not drop any extensions that might happen to
+ * own temp objects.
+ */
+ object.classId = NamespaceRelationId;
+ object.objectId = tempNamespaceId;
+ object.objectSubId = 0;
+
+ performDeletion(&object, DROP_CASCADE,
+ PERFORM_DELETION_INTERNAL |
+ PERFORM_DELETION_QUIETLY |
+ PERFORM_DELETION_SKIP_ORIGINAL |
+ PERFORM_DELETION_SKIP_EXTENSIONS);
+}
+
+/*
+ * Callback to remove temp relations at backend exit.
+ */
+static void
+RemoveTempRelationsCallback(int code, Datum arg)
+{
+ if (OidIsValid(myTempNamespace)) /* should always be true */
+ {
+ /* Need to ensure we have a usable transaction. */
+ AbortOutOfAnyTransaction();
+ StartTransactionCommand();
+
+ RemoveTempRelations(myTempNamespace);
+
+ CommitTransactionCommand();
+ }
+}
+
+/*
+ * Remove all temp tables from the temporary namespace.
+ */
+void
+ResetTempTableNamespace(void)
+{
+ if (OidIsValid(myTempNamespace))
+ RemoveTempRelations(myTempNamespace);
+}
+
+
+/*
+ * Routines for handling the GUC variable 'search_path'.
+ */
+
+/* check_hook: validate new search_path value */
+bool
+check_search_path(char **newval, void **extra, GucSource source)
+{
+ char *rawname;
+ List *namelist;
+
+ /* Need a modifiable copy of string */
+ rawname = pstrdup(*newval);
+
+ /* Parse string into list of identifiers */
+ if (!SplitIdentifierString(rawname, ',', &namelist))
+ {
+ /* syntax error in name list */
+ GUC_check_errdetail("List syntax is invalid.");
+ pfree(rawname);
+ list_free(namelist);
+ return false;
+ }
+
+ /*
+ * We used to try to check that the named schemas exist, but there are
+ * many valid use-cases for having search_path settings that include
+ * schemas that don't exist; and often, we are not inside a transaction
+ * here and so can't consult the system catalogs anyway. So now, the only
+ * requirement is syntactic validity of the identifier list.
+ */
+
+ pfree(rawname);
+ list_free(namelist);
+
+ return true;
+}
+
+/* assign_hook: do extra actions as needed */
+void
+assign_search_path(const char *newval, void *extra)
+{
+ /*
+ * We mark the path as needing recomputation, but don't do anything until
+ * it's needed. This avoids trying to do database access during GUC
+ * initialization, or outside a transaction.
+ */
+ baseSearchPathValid = false;
+}
+
+/*
+ * InitializeSearchPath: initialize module during InitPostgres.
+ *
+ * This is called after we are up enough to be able to do catalog lookups.
+ */
+void
+InitializeSearchPath(void)
+{
+ if (IsBootstrapProcessingMode())
+ {
+ /*
+ * In bootstrap mode, the search path must be 'pg_catalog' so that
+ * tables are created in the proper namespace; ignore the GUC setting.
+ */
+ MemoryContext oldcxt;
+
+ oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+ baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
+ MemoryContextSwitchTo(oldcxt);
+ baseCreationNamespace = PG_CATALOG_NAMESPACE;
+ baseTempCreationPending = false;
+ baseSearchPathValid = true;
+ namespaceUser = GetUserId();
+ activeSearchPath = baseSearchPath;
+ activeCreationNamespace = baseCreationNamespace;
+ activeTempCreationPending = baseTempCreationPending;
+ activePathGeneration++; /* pro forma */
+ }
+ else
+ {
+ /*
+ * In normal mode, arrange for a callback on any syscache invalidation
+ * of pg_namespace rows.
+ */
+ CacheRegisterSyscacheCallback(NAMESPACEOID,
+ NamespaceCallback,
+ (Datum) 0);
+ /* Force search path to be recomputed on next use */
+ baseSearchPathValid = false;
+ }
+}
+
+/*
+ * NamespaceCallback
+ * Syscache inval callback function
+ */
+static void
+NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue)
+{
+ /* Force search path to be recomputed on next use */
+ baseSearchPathValid = false;
+}
+
+/*
+ * Fetch the active search path. The return value is a palloc'ed list
+ * of OIDs; the caller is responsible for freeing this storage as
+ * appropriate.
+ *
+ * The returned list includes the implicitly-prepended namespaces only if
+ * includeImplicit is true.
+ *
+ * Note: calling this may result in a CommandCounterIncrement operation,
+ * if we have to create or clean out the temp namespace.
+ */
+List *
+fetch_search_path(bool includeImplicit)
+{
+ List *result;
+
+ recomputeNamespacePath();
+
+ /*
+ * If the temp namespace should be first, force it to exist. This is so
+ * that callers can trust the result to reflect the actual default
+ * creation namespace. It's a bit bogus to do this here, since
+ * current_schema() is supposedly a stable function without side-effects,
+ * but the alternatives seem worse.
+ */
+ if (activeTempCreationPending)
+ {
+ AccessTempTableNamespace(true);
+ recomputeNamespacePath();
+ }
+
+ result = list_copy(activeSearchPath);
+ if (!includeImplicit)
+ {
+ while (result && linitial_oid(result) != activeCreationNamespace)
+ result = list_delete_first(result);
+ }
+
+ return result;
+}
+
+/*
+ * Fetch the active search path into a caller-allocated array of OIDs.
+ * Returns the number of path entries. (If this is more than sarray_len,
+ * then the data didn't fit and is not all stored.)
+ *
+ * The returned list always includes the implicitly-prepended namespaces,
+ * but never includes the temp namespace. (This is suitable for existing
+ * users, which would want to ignore the temp namespace anyway.) This
+ * definition allows us to not worry about initializing the temp namespace.
+ */
+int
+fetch_search_path_array(Oid *sarray, int sarray_len)
+{
+ int count = 0;
+ ListCell *l;
+
+ recomputeNamespacePath();
+
+ foreach(l, activeSearchPath)
+ {
+ Oid namespaceId = lfirst_oid(l);
+
+ if (namespaceId == myTempNamespace)
+ continue; /* do not include temp namespace */
+
+ if (count < sarray_len)
+ sarray[count] = namespaceId;
+ count++;
+ }
+
+ return count;
+}
+
+
+/*
+ * Export the FooIsVisible functions as SQL-callable functions.
+ *
+ * Note: as of Postgres 8.4, these will silently return NULL if called on
+ * a nonexistent object OID, rather than failing. This is to avoid race
+ * condition errors when a query that's scanning a catalog using an MVCC
+ * snapshot uses one of these functions. The underlying IsVisible functions
+ * always use an up-to-date snapshot and so might see the object as already
+ * gone when it's still visible to the transaction snapshot. (There is no race
+ * condition in the current coding because we don't accept sinval messages
+ * between the SearchSysCacheExists test and the subsequent lookup.)
+ */
+
+Datum
+pg_table_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(RelationIsVisible(oid));
+}
+
+Datum
+pg_type_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(TYPEOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(TypeIsVisible(oid));
+}
+
+Datum
+pg_function_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(FunctionIsVisible(oid));
+}
+
+Datum
+pg_operator_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(OPEROID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(OperatorIsVisible(oid));
+}
+
+Datum
+pg_opclass_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(CLAOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(OpclassIsVisible(oid));
+}
+
+Datum
+pg_opfamily_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(OPFAMILYOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(OpfamilyIsVisible(oid));
+}
+
+Datum
+pg_collation_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(COLLOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(CollationIsVisible(oid));
+}
+
+Datum
+pg_conversion_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(CONVOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(ConversionIsVisible(oid));
+}
+
+Datum
+pg_statistics_obj_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(STATEXTOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(StatisticsObjIsVisible(oid));
+}
+
+Datum
+pg_ts_parser_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(TSPARSEROID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(TSParserIsVisible(oid));
+}
+
+Datum
+pg_ts_dict_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(TSDICTOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(TSDictionaryIsVisible(oid));
+}
+
+Datum
+pg_ts_template_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(TSTEMPLATEOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(TSTemplateIsVisible(oid));
+}
+
+Datum
+pg_ts_config_is_visible(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ if (!SearchSysCacheExists1(TSCONFIGOID, ObjectIdGetDatum(oid)))
+ PG_RETURN_NULL();
+
+ PG_RETURN_BOOL(TSConfigIsVisible(oid));
+}
+
+Datum
+pg_my_temp_schema(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_OID(myTempNamespace);
+}
+
+Datum
+pg_is_other_temp_schema(PG_FUNCTION_ARGS)
+{
+ Oid oid = PG_GETARG_OID(0);
+
+ PG_RETURN_BOOL(isOtherTempNamespace(oid));
+}
diff --git a/src/backend/catalog/objectaccess.c b/src/backend/catalog/objectaccess.c
new file mode 100644
index 0000000..17d7c56
--- /dev/null
+++ b/src/backend/catalog/objectaccess.c
@@ -0,0 +1,145 @@
+/* -------------------------------------------------------------------------
+ *
+ * objectaccess.c
+ * functions for object_access_hook on various events
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/objectaccess.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
+
+/*
+ * Hook on object accesses. This is intended as infrastructure for security
+ * and logging plugins.
+ */
+object_access_hook_type object_access_hook = NULL;
+
+/*
+ * RunObjectPostCreateHook
+ *
+ * It is entrypoint of OAT_POST_CREATE event
+ */
+void
+RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
+ bool is_internal)
+{
+ ObjectAccessPostCreate pc_arg;
+
+ /* caller should check, but just in case... */
+ Assert(object_access_hook != NULL);
+
+ memset(&pc_arg, 0, sizeof(ObjectAccessPostCreate));
+ pc_arg.is_internal = is_internal;
+
+ (*object_access_hook) (OAT_POST_CREATE,
+ classId, objectId, subId,
+ (void *) &pc_arg);
+}
+
+/*
+ * RunObjectDropHook
+ *
+ * It is entrypoint of OAT_DROP event
+ */
+void
+RunObjectDropHook(Oid classId, Oid objectId, int subId,
+ int dropflags)
+{
+ ObjectAccessDrop drop_arg;
+
+ /* caller should check, but just in case... */
+ Assert(object_access_hook != NULL);
+
+ memset(&drop_arg, 0, sizeof(ObjectAccessDrop));
+ drop_arg.dropflags = dropflags;
+
+ (*object_access_hook) (OAT_DROP,
+ classId, objectId, subId,
+ (void *) &drop_arg);
+}
+
+/*
+ * RunObjectTruncateHook
+ *
+ * It is the entrypoint of OAT_TRUNCATE event
+ */
+void
+RunObjectTruncateHook(Oid objectId)
+{
+ /* caller should check, but just in case... */
+ Assert(object_access_hook != NULL);
+
+ (*object_access_hook) (OAT_TRUNCATE,
+ RelationRelationId, objectId, 0,
+ NULL);
+}
+
+/*
+ * RunObjectPostAlterHook
+ *
+ * It is entrypoint of OAT_POST_ALTER event
+ */
+void
+RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
+ Oid auxiliaryId, bool is_internal)
+{
+ ObjectAccessPostAlter pa_arg;
+
+ /* caller should check, but just in case... */
+ Assert(object_access_hook != NULL);
+
+ memset(&pa_arg, 0, sizeof(ObjectAccessPostAlter));
+ pa_arg.auxiliary_id = auxiliaryId;
+ pa_arg.is_internal = is_internal;
+
+ (*object_access_hook) (OAT_POST_ALTER,
+ classId, objectId, subId,
+ (void *) &pa_arg);
+}
+
+/*
+ * RunNamespaceSearchHook
+ *
+ * It is entrypoint of OAT_NAMESPACE_SEARCH event
+ */
+bool
+RunNamespaceSearchHook(Oid objectId, bool ereport_on_violation)
+{
+ ObjectAccessNamespaceSearch ns_arg;
+
+ /* caller should check, but just in case... */
+ Assert(object_access_hook != NULL);
+
+ memset(&ns_arg, 0, sizeof(ObjectAccessNamespaceSearch));
+ ns_arg.ereport_on_violation = ereport_on_violation;
+ ns_arg.result = true;
+
+ (*object_access_hook) (OAT_NAMESPACE_SEARCH,
+ NamespaceRelationId, objectId, 0,
+ (void *) &ns_arg);
+
+ return ns_arg.result;
+}
+
+/*
+ * RunFunctionExecuteHook
+ *
+ * It is entrypoint of OAT_FUNCTION_EXECUTE event
+ */
+void
+RunFunctionExecuteHook(Oid objectId)
+{
+ /* caller should check, but just in case... */
+ Assert(object_access_hook != NULL);
+
+ (*object_access_hook) (OAT_FUNCTION_EXECUTE,
+ ProcedureRelationId, objectId, 0,
+ NULL);
+}
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
new file mode 100644
index 0000000..64ceccb
--- /dev/null
+++ b/src/backend/catalog/objectaddress.c
@@ -0,0 +1,5378 @@
+/*-------------------------------------------------------------------------
+ *
+ * objectaddress.c
+ * functions for working with ObjectAddresses
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/objectaddress.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/relation.h"
+#include "access/sysattr.h"
+#include "access/table.h"
+#include "catalog/catalog.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_amop.h"
+#include "catalog/pg_amproc.h"
+#include "catalog/pg_attrdef.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_cast.h"
+#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_policy.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_publication.h"
+#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"
+#include "catalog/pg_ts_dict.h"
+#include "catalog/pg_ts_parser.h"
+#include "catalog/pg_ts_template.h"
+#include "catalog/pg_type.h"
+#include "catalog/pg_user_mapping.h"
+#include "commands/dbcommands.h"
+#include "commands/defrem.h"
+#include "commands/event_trigger.h"
+#include "commands/extension.h"
+#include "commands/policy.h"
+#include "commands/proclang.h"
+#include "commands/tablespace.h"
+#include "commands/trigger.h"
+#include "foreign/foreign.h"
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "parser/parse_func.h"
+#include "parser/parse_oper.h"
+#include "parser/parse_type.h"
+#include "rewrite/rewriteSupport.h"
+#include "storage/large_object.h"
+#include "storage/lmgr.h"
+#include "storage/sinval.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/regproc.h"
+#include "utils/syscache.h"
+
+/*
+ * ObjectProperty
+ *
+ * This array provides a common part of system object structure; to help
+ * consolidate routines to handle various kind of object classes.
+ */
+typedef struct
+{
+ Oid class_oid; /* oid of catalog */
+ Oid oid_index_oid; /* oid of index on system oid column */
+ int oid_catcache_id; /* id of catcache on system oid column */
+ int name_catcache_id; /* id of catcache on (name,namespace), or
+ * (name) if the object does not live in a
+ * namespace */
+ AttrNumber attnum_oid; /* attribute number of oid column */
+ AttrNumber attnum_name; /* attnum of name field */
+ AttrNumber attnum_namespace; /* attnum of namespace field */
+ AttrNumber attnum_owner; /* attnum of owner field */
+ AttrNumber attnum_acl; /* attnum of acl field */
+ ObjectType objtype; /* OBJECT_* of this object type */
+ bool is_nsp_name_unique; /* can the nsp/name combination (or name
+ * alone, if there's no namespace) be
+ * considered a unique identifier for an
+ * object of this class? */
+} ObjectPropertyType;
+
+static const ObjectPropertyType ObjectProperty[] =
+{
+ {
+ AccessMethodRelationId,
+ AmOidIndexId,
+ AMOID,
+ AMNAME,
+ Anum_pg_am_oid,
+ Anum_pg_am_amname,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ -1,
+ true
+ },
+ {
+ CastRelationId,
+ CastOidIndexId,
+ -1,
+ -1,
+ Anum_pg_cast_oid,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ -1,
+ false
+ },
+ {
+ CollationRelationId,
+ CollationOidIndexId,
+ COLLOID,
+ -1, /* COLLNAMEENCNSP also takes encoding */
+ Anum_pg_collation_oid,
+ Anum_pg_collation_collname,
+ Anum_pg_collation_collnamespace,
+ Anum_pg_collation_collowner,
+ InvalidAttrNumber,
+ OBJECT_COLLATION,
+ true
+ },
+ {
+ ConstraintRelationId,
+ ConstraintOidIndexId,
+ CONSTROID,
+ -1,
+ Anum_pg_constraint_oid,
+ Anum_pg_constraint_conname,
+ Anum_pg_constraint_connamespace,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ -1,
+ false
+ },
+ {
+ ConversionRelationId,
+ ConversionOidIndexId,
+ CONVOID,
+ CONNAMENSP,
+ Anum_pg_conversion_oid,
+ Anum_pg_conversion_conname,
+ Anum_pg_conversion_connamespace,
+ Anum_pg_conversion_conowner,
+ InvalidAttrNumber,
+ OBJECT_CONVERSION,
+ true
+ },
+ {
+ DatabaseRelationId,
+ DatabaseOidIndexId,
+ DATABASEOID,
+ -1,
+ Anum_pg_database_oid,
+ Anum_pg_database_datname,
+ InvalidAttrNumber,
+ Anum_pg_database_datdba,
+ Anum_pg_database_datacl,
+ OBJECT_DATABASE,
+ true
+ },
+ {
+ ExtensionRelationId,
+ ExtensionOidIndexId,
+ -1,
+ -1,
+ Anum_pg_extension_oid,
+ Anum_pg_extension_extname,
+ InvalidAttrNumber, /* extension doesn't belong to extnamespace */
+ Anum_pg_extension_extowner,
+ InvalidAttrNumber,
+ OBJECT_EXTENSION,
+ true
+ },
+ {
+ ForeignDataWrapperRelationId,
+ ForeignDataWrapperOidIndexId,
+ FOREIGNDATAWRAPPEROID,
+ FOREIGNDATAWRAPPERNAME,
+ Anum_pg_foreign_data_wrapper_oid,
+ Anum_pg_foreign_data_wrapper_fdwname,
+ InvalidAttrNumber,
+ Anum_pg_foreign_data_wrapper_fdwowner,
+ Anum_pg_foreign_data_wrapper_fdwacl,
+ OBJECT_FDW,
+ true
+ },
+ {
+ ForeignServerRelationId,
+ ForeignServerOidIndexId,
+ FOREIGNSERVEROID,
+ FOREIGNSERVERNAME,
+ Anum_pg_foreign_server_oid,
+ Anum_pg_foreign_server_srvname,
+ InvalidAttrNumber,
+ Anum_pg_foreign_server_srvowner,
+ Anum_pg_foreign_server_srvacl,
+ OBJECT_FOREIGN_SERVER,
+ true
+ },
+ {
+ ProcedureRelationId,
+ ProcedureOidIndexId,
+ PROCOID,
+ -1, /* PROCNAMEARGSNSP also takes argument types */
+ Anum_pg_proc_oid,
+ Anum_pg_proc_proname,
+ Anum_pg_proc_pronamespace,
+ Anum_pg_proc_proowner,
+ Anum_pg_proc_proacl,
+ OBJECT_FUNCTION,
+ false
+ },
+ {
+ LanguageRelationId,
+ LanguageOidIndexId,
+ LANGOID,
+ LANGNAME,
+ Anum_pg_language_oid,
+ Anum_pg_language_lanname,
+ InvalidAttrNumber,
+ Anum_pg_language_lanowner,
+ Anum_pg_language_lanacl,
+ OBJECT_LANGUAGE,
+ true
+ },
+ {
+ LargeObjectMetadataRelationId,
+ LargeObjectMetadataOidIndexId,
+ -1,
+ -1,
+ Anum_pg_largeobject_metadata_oid,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ Anum_pg_largeobject_metadata_lomowner,
+ Anum_pg_largeobject_metadata_lomacl,
+ OBJECT_LARGEOBJECT,
+ false
+ },
+ {
+ OperatorClassRelationId,
+ OpclassOidIndexId,
+ CLAOID,
+ -1, /* CLAAMNAMENSP also takes opcmethod */
+ Anum_pg_opclass_oid,
+ Anum_pg_opclass_opcname,
+ Anum_pg_opclass_opcnamespace,
+ Anum_pg_opclass_opcowner,
+ InvalidAttrNumber,
+ OBJECT_OPCLASS,
+ true
+ },
+ {
+ OperatorRelationId,
+ OperatorOidIndexId,
+ OPEROID,
+ -1, /* OPERNAMENSP also takes left and right type */
+ Anum_pg_operator_oid,
+ Anum_pg_operator_oprname,
+ Anum_pg_operator_oprnamespace,
+ Anum_pg_operator_oprowner,
+ InvalidAttrNumber,
+ OBJECT_OPERATOR,
+ false
+ },
+ {
+ OperatorFamilyRelationId,
+ OpfamilyOidIndexId,
+ OPFAMILYOID,
+ -1, /* OPFAMILYAMNAMENSP also takes opfmethod */
+ Anum_pg_opfamily_oid,
+ Anum_pg_opfamily_opfname,
+ Anum_pg_opfamily_opfnamespace,
+ Anum_pg_opfamily_opfowner,
+ InvalidAttrNumber,
+ OBJECT_OPFAMILY,
+ true
+ },
+ {
+ AuthIdRelationId,
+ AuthIdOidIndexId,
+ AUTHOID,
+ AUTHNAME,
+ Anum_pg_authid_oid,
+ Anum_pg_authid_rolname,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ -1,
+ true
+ },
+ {
+ RewriteRelationId,
+ RewriteOidIndexId,
+ -1,
+ -1,
+ Anum_pg_rewrite_oid,
+ Anum_pg_rewrite_rulename,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ -1,
+ false
+ },
+ {
+ NamespaceRelationId,
+ NamespaceOidIndexId,
+ NAMESPACEOID,
+ NAMESPACENAME,
+ Anum_pg_namespace_oid,
+ Anum_pg_namespace_nspname,
+ InvalidAttrNumber,
+ Anum_pg_namespace_nspowner,
+ Anum_pg_namespace_nspacl,
+ OBJECT_SCHEMA,
+ true
+ },
+ {
+ RelationRelationId,
+ ClassOidIndexId,
+ RELOID,
+ RELNAMENSP,
+ Anum_pg_class_oid,
+ Anum_pg_class_relname,
+ Anum_pg_class_relnamespace,
+ Anum_pg_class_relowner,
+ Anum_pg_class_relacl,
+ OBJECT_TABLE,
+ true
+ },
+ {
+ TableSpaceRelationId,
+ TablespaceOidIndexId,
+ TABLESPACEOID,
+ -1,
+ Anum_pg_tablespace_oid,
+ Anum_pg_tablespace_spcname,
+ InvalidAttrNumber,
+ Anum_pg_tablespace_spcowner,
+ Anum_pg_tablespace_spcacl,
+ OBJECT_TABLESPACE,
+ true
+ },
+ {
+ TransformRelationId,
+ TransformOidIndexId,
+ TRFOID,
+ InvalidAttrNumber,
+ Anum_pg_transform_oid
+ },
+ {
+ TriggerRelationId,
+ TriggerOidIndexId,
+ -1,
+ -1,
+ Anum_pg_trigger_oid,
+ Anum_pg_trigger_tgname,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ -1,
+ false
+ },
+ {
+ PolicyRelationId,
+ PolicyOidIndexId,
+ -1,
+ -1,
+ Anum_pg_policy_oid,
+ Anum_pg_policy_polname,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ -1,
+ false
+ },
+ {
+ EventTriggerRelationId,
+ EventTriggerOidIndexId,
+ EVENTTRIGGEROID,
+ EVENTTRIGGERNAME,
+ Anum_pg_event_trigger_oid,
+ Anum_pg_event_trigger_evtname,
+ InvalidAttrNumber,
+ Anum_pg_event_trigger_evtowner,
+ InvalidAttrNumber,
+ OBJECT_EVENT_TRIGGER,
+ true
+ },
+ {
+ TSConfigRelationId,
+ TSConfigOidIndexId,
+ TSCONFIGOID,
+ TSCONFIGNAMENSP,
+ Anum_pg_ts_config_oid,
+ Anum_pg_ts_config_cfgname,
+ Anum_pg_ts_config_cfgnamespace,
+ Anum_pg_ts_config_cfgowner,
+ InvalidAttrNumber,
+ OBJECT_TSCONFIGURATION,
+ true
+ },
+ {
+ TSDictionaryRelationId,
+ TSDictionaryOidIndexId,
+ TSDICTOID,
+ TSDICTNAMENSP,
+ Anum_pg_ts_dict_oid,
+ Anum_pg_ts_dict_dictname,
+ Anum_pg_ts_dict_dictnamespace,
+ Anum_pg_ts_dict_dictowner,
+ InvalidAttrNumber,
+ OBJECT_TSDICTIONARY,
+ true
+ },
+ {
+ TSParserRelationId,
+ TSParserOidIndexId,
+ TSPARSEROID,
+ TSPARSERNAMENSP,
+ Anum_pg_ts_parser_oid,
+ Anum_pg_ts_parser_prsname,
+ Anum_pg_ts_parser_prsnamespace,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ -1,
+ true
+ },
+ {
+ TSTemplateRelationId,
+ TSTemplateOidIndexId,
+ TSTEMPLATEOID,
+ TSTEMPLATENAMENSP,
+ Anum_pg_ts_template_oid,
+ Anum_pg_ts_template_tmplname,
+ Anum_pg_ts_template_tmplnamespace,
+ InvalidAttrNumber,
+ InvalidAttrNumber,
+ -1,
+ true,
+ },
+ {
+ TypeRelationId,
+ TypeOidIndexId,
+ TYPEOID,
+ TYPENAMENSP,
+ Anum_pg_type_oid,
+ Anum_pg_type_typname,
+ Anum_pg_type_typnamespace,
+ Anum_pg_type_typowner,
+ Anum_pg_type_typacl,
+ OBJECT_TYPE,
+ true
+ },
+ {
+ PublicationRelationId,
+ PublicationObjectIndexId,
+ PUBLICATIONOID,
+ PUBLICATIONNAME,
+ Anum_pg_publication_oid,
+ Anum_pg_publication_pubname,
+ InvalidAttrNumber,
+ Anum_pg_publication_pubowner,
+ InvalidAttrNumber,
+ OBJECT_PUBLICATION,
+ true
+ },
+ {
+ SubscriptionRelationId,
+ SubscriptionObjectIndexId,
+ SUBSCRIPTIONOID,
+ SUBSCRIPTIONNAME,
+ Anum_pg_subscription_oid,
+ Anum_pg_subscription_subname,
+ InvalidAttrNumber,
+ Anum_pg_subscription_subowner,
+ InvalidAttrNumber,
+ OBJECT_SUBSCRIPTION,
+ true
+ },
+ {
+ StatisticExtRelationId,
+ StatisticExtOidIndexId,
+ STATEXTOID,
+ STATEXTNAMENSP,
+ Anum_pg_statistic_ext_oid,
+ Anum_pg_statistic_ext_stxname,
+ Anum_pg_statistic_ext_stxnamespace,
+ Anum_pg_statistic_ext_stxowner,
+ InvalidAttrNumber, /* no ACL (same as relation) */
+ OBJECT_STATISTIC_EXT,
+ true
+ }
+};
+
+/*
+ * This struct maps the string object types as returned by
+ * getObjectTypeDescription into ObjectType enum values. Note that some enum
+ * values can be obtained by different names, and that some string object types
+ * do not have corresponding values in the output enum. The user of this map
+ * must be careful to test for invalid values being returned.
+ *
+ * To ease maintenance, this follows the order of getObjectTypeDescription.
+ */
+static const struct object_type_map
+{
+ const char *tm_name;
+ ObjectType tm_type;
+}
+
+ ObjectTypeMap[] =
+{
+ /* OCLASS_CLASS, all kinds of relations */
+ {
+ "table", OBJECT_TABLE
+ },
+ {
+ "index", OBJECT_INDEX
+ },
+ {
+ "sequence", OBJECT_SEQUENCE
+ },
+ {
+ "toast table", -1
+ }, /* unmapped */
+ {
+ "view", OBJECT_VIEW
+ },
+ {
+ "materialized view", OBJECT_MATVIEW
+ },
+ {
+ "composite type", -1
+ }, /* unmapped */
+ {
+ "foreign table", OBJECT_FOREIGN_TABLE
+ },
+ {
+ "table column", OBJECT_COLUMN
+ },
+ {
+ "index column", -1
+ }, /* unmapped */
+ {
+ "sequence column", -1
+ }, /* unmapped */
+ {
+ "toast table column", -1
+ }, /* unmapped */
+ {
+ "view column", -1
+ }, /* unmapped */
+ {
+ "materialized view column", -1
+ }, /* unmapped */
+ {
+ "composite type column", -1
+ }, /* unmapped */
+ {
+ "foreign table column", OBJECT_COLUMN
+ },
+ /* OCLASS_PROC */
+ {
+ "aggregate", OBJECT_AGGREGATE
+ },
+ {
+ "function", OBJECT_FUNCTION
+ },
+ {
+ "procedure", OBJECT_PROCEDURE
+ },
+ /* OCLASS_TYPE */
+ {
+ "type", OBJECT_TYPE
+ },
+ /* OCLASS_CAST */
+ {
+ "cast", OBJECT_CAST
+ },
+ /* OCLASS_COLLATION */
+ {
+ "collation", OBJECT_COLLATION
+ },
+ /* OCLASS_CONSTRAINT */
+ {
+ "table constraint", OBJECT_TABCONSTRAINT
+ },
+ {
+ "domain constraint", OBJECT_DOMCONSTRAINT
+ },
+ /* OCLASS_CONVERSION */
+ {
+ "conversion", OBJECT_CONVERSION
+ },
+ /* OCLASS_DEFAULT */
+ {
+ "default value", OBJECT_DEFAULT
+ },
+ /* OCLASS_LANGUAGE */
+ {
+ "language", OBJECT_LANGUAGE
+ },
+ /* OCLASS_LARGEOBJECT */
+ {
+ "large object", OBJECT_LARGEOBJECT
+ },
+ /* OCLASS_OPERATOR */
+ {
+ "operator", OBJECT_OPERATOR
+ },
+ /* OCLASS_OPCLASS */
+ {
+ "operator class", OBJECT_OPCLASS
+ },
+ /* OCLASS_OPFAMILY */
+ {
+ "operator family", OBJECT_OPFAMILY
+ },
+ /* OCLASS_AM */
+ {
+ "access method", OBJECT_ACCESS_METHOD
+ },
+ /* OCLASS_AMOP */
+ {
+ "operator of access method", OBJECT_AMOP
+ },
+ /* OCLASS_AMPROC */
+ {
+ "function of access method", OBJECT_AMPROC
+ },
+ /* OCLASS_REWRITE */
+ {
+ "rule", OBJECT_RULE
+ },
+ /* OCLASS_TRIGGER */
+ {
+ "trigger", OBJECT_TRIGGER
+ },
+ /* OCLASS_SCHEMA */
+ {
+ "schema", OBJECT_SCHEMA
+ },
+ /* OCLASS_TSPARSER */
+ {
+ "text search parser", OBJECT_TSPARSER
+ },
+ /* OCLASS_TSDICT */
+ {
+ "text search dictionary", OBJECT_TSDICTIONARY
+ },
+ /* OCLASS_TSTEMPLATE */
+ {
+ "text search template", OBJECT_TSTEMPLATE
+ },
+ /* OCLASS_TSCONFIG */
+ {
+ "text search configuration", OBJECT_TSCONFIGURATION
+ },
+ /* OCLASS_ROLE */
+ {
+ "role", OBJECT_ROLE
+ },
+ /* OCLASS_DATABASE */
+ {
+ "database", OBJECT_DATABASE
+ },
+ /* OCLASS_TBLSPACE */
+ {
+ "tablespace", OBJECT_TABLESPACE
+ },
+ /* OCLASS_FDW */
+ {
+ "foreign-data wrapper", OBJECT_FDW
+ },
+ /* OCLASS_FOREIGN_SERVER */
+ {
+ "server", OBJECT_FOREIGN_SERVER
+ },
+ /* OCLASS_USER_MAPPING */
+ {
+ "user mapping", OBJECT_USER_MAPPING
+ },
+ /* OCLASS_DEFACL */
+ {
+ "default acl", OBJECT_DEFACL
+ },
+ /* OCLASS_EXTENSION */
+ {
+ "extension", OBJECT_EXTENSION
+ },
+ /* OCLASS_EVENT_TRIGGER */
+ {
+ "event trigger", OBJECT_EVENT_TRIGGER
+ },
+ /* OCLASS_POLICY */
+ {
+ "policy", OBJECT_POLICY
+ },
+ /* OCLASS_PUBLICATION */
+ {
+ "publication", OBJECT_PUBLICATION
+ },
+ /* OCLASS_PUBLICATION_REL */
+ {
+ "publication relation", OBJECT_PUBLICATION_REL
+ },
+ /* OCLASS_SUBSCRIPTION */
+ {
+ "subscription", OBJECT_SUBSCRIPTION
+ },
+ /* OCLASS_TRANSFORM */
+ {
+ "transform", OBJECT_TRANSFORM
+ },
+ /* OCLASS_STATISTIC_EXT */
+ {
+ "statistics object", OBJECT_STATISTIC_EXT
+ }
+};
+
+const ObjectAddress InvalidObjectAddress =
+{
+ InvalidOid,
+ InvalidOid,
+ 0
+};
+
+static ObjectAddress get_object_address_unqualified(ObjectType objtype,
+ Value *strval, bool missing_ok);
+static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
+ List *object, Relation *relp,
+ LOCKMODE lockmode, bool missing_ok);
+static ObjectAddress get_object_address_relobject(ObjectType objtype,
+ List *object, Relation *relp, bool missing_ok);
+static ObjectAddress get_object_address_attribute(ObjectType objtype,
+ List *object, Relation *relp,
+ LOCKMODE lockmode, bool missing_ok);
+static ObjectAddress get_object_address_attrdef(ObjectType objtype,
+ List *object, Relation *relp, LOCKMODE lockmode,
+ bool missing_ok);
+static ObjectAddress get_object_address_type(ObjectType objtype,
+ TypeName *typename, bool missing_ok);
+static ObjectAddress get_object_address_opcf(ObjectType objtype, List *object,
+ bool missing_ok);
+static ObjectAddress get_object_address_opf_member(ObjectType objtype,
+ List *object, bool missing_ok);
+
+static ObjectAddress get_object_address_usermapping(List *object,
+ bool missing_ok);
+static ObjectAddress get_object_address_publication_rel(List *object,
+ Relation *relp,
+ bool missing_ok);
+static ObjectAddress get_object_address_defacl(List *object,
+ bool missing_ok);
+static const ObjectPropertyType *get_object_property_data(Oid class_id);
+
+static void getRelationDescription(StringInfo buffer, Oid relid);
+static void getOpFamilyDescription(StringInfo buffer, Oid opfid);
+static void getRelationTypeDescription(StringInfo buffer, Oid relid,
+ int32 objectSubId);
+static void getProcedureTypeDescription(StringInfo buffer, Oid procid);
+static void getConstraintTypeDescription(StringInfo buffer, Oid constroid);
+static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object);
+static void getRelationIdentity(StringInfo buffer, Oid relid, List **object);
+
+/*
+ * Translate an object name and arguments (as passed by the parser) to an
+ * ObjectAddress.
+ *
+ * The returned object will be locked using the specified lockmode. If a
+ * sub-object is looked up, the parent object will be locked instead.
+ *
+ * If the object is a relation or a child object of a relation (e.g. an
+ * attribute or constraint), the relation is also opened and *relp receives
+ * the open relcache entry pointer; otherwise, *relp is set to NULL. This
+ * is a bit grotty but it makes life simpler, since the caller will
+ * typically need the relcache entry too. Caller must close the relcache
+ * entry when done with it. The relation is locked with the specified lockmode
+ * if the target object is the relation itself or an attribute, but for other
+ * child objects, only AccessShareLock is acquired on the relation.
+ *
+ * If the object is not found, an error is thrown, unless missing_ok is
+ * true. In this case, no lock is acquired, relp is set to NULL, and the
+ * returned address has objectId set to InvalidOid.
+ *
+ * We don't currently provide a function to release the locks acquired here;
+ * typically, the lock must be held until commit to guard against a concurrent
+ * drop operation.
+ *
+ * Note: If the object is not found, we don't give any indication of the
+ * reason. (It might have been a missing schema if the name was qualified, or
+ * a nonexistent type name in case of a cast, function or operator; etc).
+ * Currently there is only one caller that might be interested in such info, so
+ * we don't spend much effort here. If more callers start to care, it might be
+ * better to add some support for that in this function.
+ */
+ObjectAddress
+get_object_address(ObjectType objtype, Node *object,
+ Relation *relp, LOCKMODE lockmode, bool missing_ok)
+{
+ ObjectAddress address;
+ ObjectAddress old_address = {InvalidOid, InvalidOid, 0};
+ Relation relation = NULL;
+ uint64 inval_count;
+
+ /* Some kind of lock must be taken. */
+ Assert(lockmode != NoLock);
+
+ for (;;)
+ {
+ /*
+ * Remember this value, so that, after looking up the object name and
+ * locking it, we can check whether any invalidation messages have
+ * been processed that might require a do-over.
+ */
+ inval_count = SharedInvalidMessageCounter;
+
+ /* Look up object address. */
+ switch (objtype)
+ {
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ address =
+ get_relation_by_qualified_name(objtype, castNode(List, object),
+ &relation, lockmode,
+ missing_ok);
+ break;
+ case OBJECT_COLUMN:
+ address =
+ get_object_address_attribute(objtype, castNode(List, object),
+ &relation, lockmode,
+ missing_ok);
+ break;
+ case OBJECT_DEFAULT:
+ address =
+ get_object_address_attrdef(objtype, castNode(List, object),
+ &relation, lockmode,
+ missing_ok);
+ break;
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_POLICY:
+ address = get_object_address_relobject(objtype, castNode(List, object),
+ &relation, missing_ok);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ {
+ List *objlist;
+ ObjectAddress domaddr;
+ char *constrname;
+
+ objlist = castNode(List, object);
+ domaddr = get_object_address_type(OBJECT_DOMAIN,
+ linitial_node(TypeName, objlist),
+ missing_ok);
+ constrname = strVal(lsecond(objlist));
+
+ address.classId = ConstraintRelationId;
+ address.objectId = get_domain_constraint_oid(domaddr.objectId,
+ constrname, missing_ok);
+ address.objectSubId = 0;
+
+ }
+ break;
+ case OBJECT_DATABASE:
+ case OBJECT_EXTENSION:
+ case OBJECT_TABLESPACE:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_LANGUAGE:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_PUBLICATION:
+ case OBJECT_SUBSCRIPTION:
+ address = get_object_address_unqualified(objtype,
+ (Value *) object, missing_ok);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ address = get_object_address_type(objtype, castNode(TypeName, object), missing_ok);
+ break;
+ case OBJECT_AGGREGATE:
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ address.classId = ProcedureRelationId;
+ address.objectId = LookupFuncWithArgs(objtype, castNode(ObjectWithArgs, object), missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_OPERATOR:
+ address.classId = OperatorRelationId;
+ address.objectId = LookupOperWithArgs(castNode(ObjectWithArgs, object), missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_COLLATION:
+ address.classId = CollationRelationId;
+ address.objectId = get_collation_oid(castNode(List, object), missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_CONVERSION:
+ address.classId = ConversionRelationId;
+ address.objectId = get_conversion_oid(castNode(List, object), missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ address = get_object_address_opcf(objtype, castNode(List, object), missing_ok);
+ break;
+ case OBJECT_AMOP:
+ case OBJECT_AMPROC:
+ address = get_object_address_opf_member(objtype, castNode(List, object), missing_ok);
+ break;
+ case OBJECT_LARGEOBJECT:
+ address.classId = LargeObjectRelationId;
+ address.objectId = oidparse(object);
+ address.objectSubId = 0;
+ if (!LargeObjectExists(address.objectId))
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("large object %u does not exist",
+ address.objectId)));
+ }
+ break;
+ case OBJECT_CAST:
+ {
+ TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
+ TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
+ Oid sourcetypeid;
+ Oid targettypeid;
+
+ sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
+ targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
+ address.classId = CastRelationId;
+ address.objectId =
+ get_cast_oid(sourcetypeid, targettypeid, missing_ok);
+ address.objectSubId = 0;
+ }
+ break;
+ case OBJECT_TRANSFORM:
+ {
+ TypeName *typename = linitial_node(TypeName, castNode(List, object));
+ char *langname = strVal(lsecond(castNode(List, object)));
+ Oid type_id = LookupTypeNameOid(NULL, typename, missing_ok);
+ Oid lang_id = get_language_oid(langname, missing_ok);
+
+ address.classId = TransformRelationId;
+ address.objectId =
+ get_transform_oid(type_id, lang_id, missing_ok);
+ address.objectSubId = 0;
+ }
+ break;
+ case OBJECT_TSPARSER:
+ address.classId = TSParserRelationId;
+ address.objectId = get_ts_parser_oid(castNode(List, object), missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_TSDICTIONARY:
+ address.classId = TSDictionaryRelationId;
+ address.objectId = get_ts_dict_oid(castNode(List, object), missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_TSTEMPLATE:
+ address.classId = TSTemplateRelationId;
+ address.objectId = get_ts_template_oid(castNode(List, object), missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_TSCONFIGURATION:
+ address.classId = TSConfigRelationId;
+ address.objectId = get_ts_config_oid(castNode(List, object), missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_USER_MAPPING:
+ address = get_object_address_usermapping(castNode(List, object),
+ missing_ok);
+ break;
+ case OBJECT_PUBLICATION_REL:
+ address = get_object_address_publication_rel(castNode(List, object),
+ &relation,
+ missing_ok);
+ break;
+ case OBJECT_DEFACL:
+ address = get_object_address_defacl(castNode(List, object),
+ missing_ok);
+ break;
+ case OBJECT_STATISTIC_EXT:
+ address.classId = StatisticExtRelationId;
+ address.objectId = get_statistics_object_oid(castNode(List, object),
+ missing_ok);
+ address.objectSubId = 0;
+ break;
+ default:
+ elog(ERROR, "unrecognized objtype: %d", (int) objtype);
+ /* placate compiler, in case it thinks elog might return */
+ address.classId = InvalidOid;
+ address.objectId = InvalidOid;
+ address.objectSubId = 0;
+ }
+
+ /*
+ * If we could not find the supplied object, return without locking.
+ */
+ if (!OidIsValid(address.objectId))
+ {
+ Assert(missing_ok);
+ return address;
+ }
+
+ /*
+ * If we're retrying, see if we got the same answer as last time. If
+ * so, we're done; if not, we locked the wrong thing, so give up our
+ * lock.
+ */
+ if (OidIsValid(old_address.classId))
+ {
+ if (old_address.classId == address.classId
+ && old_address.objectId == address.objectId
+ && old_address.objectSubId == address.objectSubId)
+ break;
+ if (old_address.classId != RelationRelationId)
+ {
+ if (IsSharedRelation(old_address.classId))
+ UnlockSharedObject(old_address.classId,
+ old_address.objectId,
+ 0, lockmode);
+ else
+ UnlockDatabaseObject(old_address.classId,
+ old_address.objectId,
+ 0, lockmode);
+ }
+ }
+
+ /*
+ * If we're dealing with a relation or attribute, then the relation is
+ * already locked. Otherwise, we lock it now.
+ */
+ if (address.classId != RelationRelationId)
+ {
+ if (IsSharedRelation(address.classId))
+ LockSharedObject(address.classId, address.objectId, 0,
+ lockmode);
+ else
+ LockDatabaseObject(address.classId, address.objectId, 0,
+ lockmode);
+ }
+
+ /*
+ * At this point, we've resolved the name to an OID and locked the
+ * corresponding database object. However, it's possible that by the
+ * time we acquire the lock on the object, concurrent DDL has modified
+ * the database in such a way that the name we originally looked up no
+ * longer resolves to that OID.
+ *
+ * We can be certain that this isn't an issue if (a) no shared
+ * invalidation messages have been processed or (b) we've locked a
+ * relation somewhere along the line. All the relation name lookups
+ * in this module ultimately use RangeVarGetRelid() to acquire a
+ * relation lock, and that function protects against the same kinds of
+ * races we're worried about here. Even when operating on a
+ * constraint, rule, or trigger, we still acquire AccessShareLock on
+ * the relation, which is enough to freeze out any concurrent DDL.
+ *
+ * In all other cases, however, it's possible that the name we looked
+ * up no longer refers to the object we locked, so we retry the lookup
+ * and see whether we get the same answer.
+ */
+ if (inval_count == SharedInvalidMessageCounter || relation != NULL)
+ break;
+ old_address = address;
+ }
+
+ /* Return the object address and the relation. */
+ *relp = relation;
+ return address;
+}
+
+/*
+ * Return an ObjectAddress based on a RangeVar and an object name. The
+ * name of the relation identified by the RangeVar is prepended to the
+ * (possibly empty) list passed in as object. This is useful to find
+ * the ObjectAddress of objects that depend on a relation. All other
+ * considerations are exactly as for get_object_address above.
+ */
+ObjectAddress
+get_object_address_rv(ObjectType objtype, RangeVar *rel, List *object,
+ Relation *relp, LOCKMODE lockmode,
+ bool missing_ok)
+{
+ if (rel)
+ {
+ object = lcons(makeString(rel->relname), object);
+ if (rel->schemaname)
+ object = lcons(makeString(rel->schemaname), object);
+ if (rel->catalogname)
+ object = lcons(makeString(rel->catalogname), object);
+ }
+
+ return get_object_address(objtype, (Node *) object,
+ relp, lockmode, missing_ok);
+}
+
+/*
+ * Find an ObjectAddress for a type of object that is identified by an
+ * unqualified name.
+ */
+static ObjectAddress
+get_object_address_unqualified(ObjectType objtype,
+ Value *strval, bool missing_ok)
+{
+ const char *name;
+ ObjectAddress address;
+
+ name = strVal(strval);
+
+ /* Translate name to OID. */
+ switch (objtype)
+ {
+ case OBJECT_ACCESS_METHOD:
+ address.classId = AccessMethodRelationId;
+ address.objectId = get_am_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_DATABASE:
+ address.classId = DatabaseRelationId;
+ address.objectId = get_database_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_EXTENSION:
+ address.classId = ExtensionRelationId;
+ address.objectId = get_extension_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_TABLESPACE:
+ address.classId = TableSpaceRelationId;
+ address.objectId = get_tablespace_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_ROLE:
+ address.classId = AuthIdRelationId;
+ address.objectId = get_role_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_SCHEMA:
+ address.classId = NamespaceRelationId;
+ address.objectId = get_namespace_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_LANGUAGE:
+ address.classId = LanguageRelationId;
+ address.objectId = get_language_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_FDW:
+ address.classId = ForeignDataWrapperRelationId;
+ address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ address.classId = ForeignServerRelationId;
+ address.objectId = get_foreign_server_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ address.classId = EventTriggerRelationId;
+ address.objectId = get_event_trigger_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_PUBLICATION:
+ address.classId = PublicationRelationId;
+ address.objectId = get_publication_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_SUBSCRIPTION:
+ address.classId = SubscriptionRelationId;
+ address.objectId = get_subscription_oid(name, missing_ok);
+ address.objectSubId = 0;
+ break;
+ default:
+ elog(ERROR, "unrecognized objtype: %d", (int) objtype);
+ /* placate compiler, which doesn't know elog won't return */
+ address.classId = InvalidOid;
+ address.objectId = InvalidOid;
+ address.objectSubId = 0;
+ }
+
+ return address;
+}
+
+/*
+ * Locate a relation by qualified name.
+ */
+static ObjectAddress
+get_relation_by_qualified_name(ObjectType objtype, List *object,
+ Relation *relp, LOCKMODE lockmode,
+ bool missing_ok)
+{
+ Relation relation;
+ ObjectAddress address;
+
+ address.classId = RelationRelationId;
+ address.objectId = InvalidOid;
+ address.objectSubId = 0;
+
+ relation = relation_openrv_extended(makeRangeVarFromNameList(object),
+ lockmode, missing_ok);
+ if (!relation)
+ return address;
+
+ switch (objtype)
+ {
+ case OBJECT_INDEX:
+ if (relation->rd_rel->relkind != RELKIND_INDEX &&
+ relation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not an index",
+ RelationGetRelationName(relation))));
+ break;
+ case OBJECT_SEQUENCE:
+ if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ RelationGetRelationName(relation))));
+ break;
+ case OBJECT_TABLE:
+ if (relation->rd_rel->relkind != RELKIND_RELATION &&
+ relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a table",
+ RelationGetRelationName(relation))));
+ break;
+ case OBJECT_VIEW:
+ if (relation->rd_rel->relkind != RELKIND_VIEW)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a view",
+ RelationGetRelationName(relation))));
+ break;
+ case OBJECT_MATVIEW:
+ if (relation->rd_rel->relkind != RELKIND_MATVIEW)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a materialized view",
+ RelationGetRelationName(relation))));
+ break;
+ case OBJECT_FOREIGN_TABLE:
+ if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a foreign table",
+ RelationGetRelationName(relation))));
+ break;
+ default:
+ elog(ERROR, "unrecognized objtype: %d", (int) objtype);
+ break;
+ }
+
+ /* Done. */
+ address.objectId = RelationGetRelid(relation);
+ *relp = relation;
+
+ return address;
+}
+
+/*
+ * Find object address for an object that is attached to a relation.
+ *
+ * Note that we take only an AccessShareLock on the relation. We need not
+ * pass down the LOCKMODE from get_object_address(), because that is the lock
+ * mode for the object itself, not the relation to which it is attached.
+ */
+static ObjectAddress
+get_object_address_relobject(ObjectType objtype, List *object,
+ Relation *relp, bool missing_ok)
+{
+ ObjectAddress address;
+ Relation relation = NULL;
+ int nnames;
+ const char *depname;
+ List *relname;
+ Oid reloid;
+
+ /* Extract name of dependent object. */
+ depname = strVal(llast(object));
+
+ /* Separate relation name from dependent object name. */
+ nnames = list_length(object);
+ if (nnames < 2)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("must specify relation and object name")));
+
+ /* Extract relation name and open relation. */
+ relname = list_truncate(list_copy(object), nnames - 1);
+ relation = table_openrv_extended(makeRangeVarFromNameList(relname),
+ AccessShareLock,
+ missing_ok);
+
+ reloid = relation ? RelationGetRelid(relation) : InvalidOid;
+
+ switch (objtype)
+ {
+ case OBJECT_RULE:
+ address.classId = RewriteRelationId;
+ address.objectId = relation ?
+ get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
+ address.objectSubId = 0;
+ break;
+ case OBJECT_TRIGGER:
+ address.classId = TriggerRelationId;
+ address.objectId = relation ?
+ get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
+ address.objectSubId = 0;
+ break;
+ case OBJECT_TABCONSTRAINT:
+ address.classId = ConstraintRelationId;
+ address.objectId = relation ?
+ get_relation_constraint_oid(reloid, depname, missing_ok) :
+ InvalidOid;
+ address.objectSubId = 0;
+ break;
+ case OBJECT_POLICY:
+ address.classId = PolicyRelationId;
+ address.objectId = relation ?
+ get_relation_policy_oid(reloid, depname, missing_ok) :
+ InvalidOid;
+ address.objectSubId = 0;
+ break;
+ default:
+ elog(ERROR, "unrecognized objtype: %d", (int) objtype);
+ }
+
+ /* Avoid relcache leak when object not found. */
+ if (!OidIsValid(address.objectId))
+ {
+ if (relation != NULL)
+ table_close(relation, AccessShareLock);
+
+ relation = NULL; /* department of accident prevention */
+ return address;
+ }
+
+ /* Done. */
+ *relp = relation;
+ return address;
+}
+
+/*
+ * Find the ObjectAddress for an attribute.
+ */
+static ObjectAddress
+get_object_address_attribute(ObjectType objtype, List *object,
+ Relation *relp, LOCKMODE lockmode,
+ bool missing_ok)
+{
+ ObjectAddress address;
+ List *relname;
+ Oid reloid;
+ Relation relation;
+ const char *attname;
+ AttrNumber attnum;
+
+ /* Extract relation name and open relation. */
+ if (list_length(object) < 2)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("column name must be qualified")));
+ attname = strVal(lfirst(list_tail(object)));
+ relname = list_truncate(list_copy(object), list_length(object) - 1);
+ /* XXX no missing_ok support here */
+ relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
+ reloid = RelationGetRelid(relation);
+
+ /* Look up attribute and construct return value. */
+ attnum = get_attnum(reloid, attname);
+ if (attnum == InvalidAttrNumber)
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ attname, NameListToString(relname))));
+
+ address.classId = RelationRelationId;
+ address.objectId = InvalidOid;
+ address.objectSubId = InvalidAttrNumber;
+ relation_close(relation, lockmode);
+ return address;
+ }
+
+ address.classId = RelationRelationId;
+ address.objectId = reloid;
+ address.objectSubId = attnum;
+
+ *relp = relation;
+ return address;
+}
+
+/*
+ * Find the ObjectAddress for an attribute's default value.
+ */
+static ObjectAddress
+get_object_address_attrdef(ObjectType objtype, List *object,
+ Relation *relp, LOCKMODE lockmode,
+ bool missing_ok)
+{
+ ObjectAddress address;
+ List *relname;
+ Oid reloid;
+ Relation relation;
+ const char *attname;
+ AttrNumber attnum;
+ TupleDesc tupdesc;
+ Oid defoid;
+
+ /* Extract relation name and open relation. */
+ if (list_length(object) < 2)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("column name must be qualified")));
+ attname = strVal(llast(object));
+ relname = list_truncate(list_copy(object), list_length(object) - 1);
+ /* XXX no missing_ok support here */
+ relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
+ reloid = RelationGetRelid(relation);
+
+ tupdesc = RelationGetDescr(relation);
+
+ /* Look up attribute number and scan pg_attrdef to find its tuple */
+ attnum = get_attnum(reloid, attname);
+ defoid = InvalidOid;
+ if (attnum != InvalidAttrNumber && tupdesc->constr != NULL)
+ {
+ Relation attrdef;
+ ScanKeyData keys[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ attrdef = relation_open(AttrDefaultRelationId, AccessShareLock);
+ ScanKeyInit(&keys[0],
+ Anum_pg_attrdef_adrelid,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(reloid));
+ ScanKeyInit(&keys[1],
+ Anum_pg_attrdef_adnum,
+ BTEqualStrategyNumber,
+ F_INT2EQ,
+ Int16GetDatum(attnum));
+ scan = systable_beginscan(attrdef, AttrDefaultIndexId, true,
+ NULL, 2, keys);
+ if (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_attrdef atdform = (Form_pg_attrdef) GETSTRUCT(tup);
+
+ defoid = atdform->oid;
+ }
+
+ systable_endscan(scan);
+ relation_close(attrdef, AccessShareLock);
+ }
+ if (!OidIsValid(defoid))
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("default value for column \"%s\" of relation \"%s\" does not exist",
+ attname, NameListToString(relname))));
+
+ address.classId = AttrDefaultRelationId;
+ address.objectId = InvalidOid;
+ address.objectSubId = InvalidAttrNumber;
+ relation_close(relation, lockmode);
+ return address;
+ }
+
+ address.classId = AttrDefaultRelationId;
+ address.objectId = defoid;
+ address.objectSubId = 0;
+
+ *relp = relation;
+ return address;
+}
+
+/*
+ * Find the ObjectAddress for a type or domain
+ */
+static ObjectAddress
+get_object_address_type(ObjectType objtype, TypeName *typename, bool missing_ok)
+{
+ ObjectAddress address;
+ Type tup;
+
+ address.classId = TypeRelationId;
+ address.objectId = InvalidOid;
+ address.objectSubId = 0;
+
+ tup = LookupTypeName(NULL, typename, NULL, missing_ok);
+ if (!HeapTupleIsValid(tup))
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("type \"%s\" does not exist",
+ TypeNameToString(typename))));
+ return address;
+ }
+ address.objectId = typeTypeId(tup);
+
+ if (objtype == OBJECT_DOMAIN)
+ {
+ if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a domain",
+ TypeNameToString(typename))));
+ }
+
+ ReleaseSysCache(tup);
+
+ return address;
+}
+
+/*
+ * Find the ObjectAddress for an opclass or opfamily.
+ */
+static ObjectAddress
+get_object_address_opcf(ObjectType objtype, List *object, bool missing_ok)
+{
+ Oid amoid;
+ ObjectAddress address;
+
+ /* XXX no missing_ok support here */
+ amoid = get_index_am_oid(strVal(linitial(object)), false);
+ object = list_copy_tail(object, 1);
+
+ switch (objtype)
+ {
+ case OBJECT_OPCLASS:
+ address.classId = OperatorClassRelationId;
+ address.objectId = get_opclass_oid(amoid, object, missing_ok);
+ address.objectSubId = 0;
+ break;
+ case OBJECT_OPFAMILY:
+ address.classId = OperatorFamilyRelationId;
+ address.objectId = get_opfamily_oid(amoid, object, missing_ok);
+ address.objectSubId = 0;
+ break;
+ default:
+ elog(ERROR, "unrecognized objtype: %d", (int) objtype);
+ /* placate compiler, which doesn't know elog won't return */
+ address.classId = InvalidOid;
+ address.objectId = InvalidOid;
+ address.objectSubId = 0;
+ }
+
+ return address;
+}
+
+/*
+ * Find the ObjectAddress for an opclass/opfamily member.
+ *
+ * (The returned address corresponds to a pg_amop/pg_amproc object).
+ */
+static ObjectAddress
+get_object_address_opf_member(ObjectType objtype,
+ List *object, bool missing_ok)
+{
+ ObjectAddress famaddr;
+ ObjectAddress address;
+ ListCell *cell;
+ List *copy;
+ TypeName *typenames[2];
+ Oid typeoids[2];
+ int membernum;
+ int i;
+
+ /*
+ * The last element of the object list contains the strategy or procedure
+ * number. We need to strip that out before getting the opclass/family
+ * address. The rest can be used directly by get_object_address_opcf().
+ */
+ membernum = atoi(strVal(llast(linitial(object))));
+ copy = list_truncate(list_copy(linitial(object)), list_length(linitial(object)) - 1);
+
+ /* no missing_ok support here */
+ famaddr = get_object_address_opcf(OBJECT_OPFAMILY, copy, false);
+
+ /* find out left/right type names and OIDs */
+ typenames[0] = typenames[1] = NULL;
+ typeoids[0] = typeoids[1] = InvalidOid;
+ i = 0;
+ foreach(cell, lsecond(object))
+ {
+ ObjectAddress typaddr;
+
+ typenames[i] = lfirst_node(TypeName, cell);
+ typaddr = get_object_address_type(OBJECT_TYPE, typenames[i], missing_ok);
+ typeoids[i] = typaddr.objectId;
+ if (++i >= 2)
+ break;
+ }
+
+ switch (objtype)
+ {
+ case OBJECT_AMOP:
+ {
+ HeapTuple tp;
+
+ ObjectAddressSet(address, AccessMethodOperatorRelationId,
+ InvalidOid);
+
+ tp = SearchSysCache4(AMOPSTRATEGY,
+ ObjectIdGetDatum(famaddr.objectId),
+ ObjectIdGetDatum(typeoids[0]),
+ ObjectIdGetDatum(typeoids[1]),
+ Int16GetDatum(membernum));
+ if (!HeapTupleIsValid(tp))
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("operator %d (%s, %s) of %s does not exist",
+ membernum,
+ TypeNameToString(typenames[0]),
+ TypeNameToString(typenames[1]),
+ getObjectDescription(&famaddr))));
+ }
+ else
+ {
+ address.objectId = ((Form_pg_amop) GETSTRUCT(tp))->oid;
+ ReleaseSysCache(tp);
+ }
+ }
+ break;
+
+ case OBJECT_AMPROC:
+ {
+ HeapTuple tp;
+
+ ObjectAddressSet(address, AccessMethodProcedureRelationId,
+ InvalidOid);
+
+ tp = SearchSysCache4(AMPROCNUM,
+ ObjectIdGetDatum(famaddr.objectId),
+ ObjectIdGetDatum(typeoids[0]),
+ ObjectIdGetDatum(typeoids[1]),
+ Int16GetDatum(membernum));
+ if (!HeapTupleIsValid(tp))
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("function %d (%s, %s) of %s does not exist",
+ membernum,
+ TypeNameToString(typenames[0]),
+ TypeNameToString(typenames[1]),
+ getObjectDescription(&famaddr))));
+ }
+ else
+ {
+ address.objectId = ((Form_pg_amproc) GETSTRUCT(tp))->oid;
+ ReleaseSysCache(tp);
+ }
+ }
+ break;
+ default:
+ elog(ERROR, "unrecognized objtype: %d", (int) objtype);
+ }
+
+ return address;
+}
+
+/*
+ * Find the ObjectAddress for a user mapping.
+ */
+static ObjectAddress
+get_object_address_usermapping(List *object, bool missing_ok)
+{
+ ObjectAddress address;
+ Oid userid;
+ char *username;
+ char *servername;
+ ForeignServer *server;
+ HeapTuple tp;
+
+ ObjectAddressSet(address, UserMappingRelationId, InvalidOid);
+
+ /* fetch string names from input lists, for error messages */
+ username = strVal(linitial(object));
+ servername = strVal(lsecond(object));
+
+ /* look up pg_authid OID of mapped user; InvalidOid if PUBLIC */
+ if (strcmp(username, "public") == 0)
+ userid = InvalidOid;
+ else
+ {
+ tp = SearchSysCache1(AUTHNAME,
+ CStringGetDatum(username));
+ if (!HeapTupleIsValid(tp))
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
+ username, servername)));
+ return address;
+ }
+ userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
+ ReleaseSysCache(tp);
+ }
+
+ /* Now look up the pg_user_mapping tuple */
+ server = GetForeignServerByName(servername, true);
+ if (!server)
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("server \"%s\" does not exist", servername)));
+ return address;
+ }
+ tp = SearchSysCache2(USERMAPPINGUSERSERVER,
+ ObjectIdGetDatum(userid),
+ ObjectIdGetDatum(server->serverid));
+ if (!HeapTupleIsValid(tp))
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
+ username, servername)));
+ return address;
+ }
+
+ address.objectId = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
+
+ ReleaseSysCache(tp);
+
+ return address;
+}
+
+/*
+ * Find the ObjectAddress for a publication relation. The first element of
+ * the object parameter is the relation name, the second is the
+ * publication name.
+ */
+static ObjectAddress
+get_object_address_publication_rel(List *object,
+ Relation *relp, bool missing_ok)
+{
+ ObjectAddress address;
+ Relation relation;
+ List *relname;
+ char *pubname;
+ Publication *pub;
+
+ ObjectAddressSet(address, PublicationRelRelationId, InvalidOid);
+
+ relname = linitial(object);
+ relation = relation_openrv_extended(makeRangeVarFromNameList(relname),
+ AccessShareLock, missing_ok);
+ if (!relation)
+ return address;
+
+ /* fetch publication name from input list */
+ pubname = strVal(lsecond(object));
+
+ /* Now look up the pg_publication tuple */
+ pub = GetPublicationByName(pubname, missing_ok);
+ if (!pub)
+ {
+ relation_close(relation, AccessShareLock);
+ return address;
+ }
+
+ /* Find the publication relation mapping in syscache. */
+ address.objectId =
+ GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
+ ObjectIdGetDatum(RelationGetRelid(relation)),
+ ObjectIdGetDatum(pub->oid));
+ if (!OidIsValid(address.objectId))
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
+ RelationGetRelationName(relation), pubname)));
+ relation_close(relation, AccessShareLock);
+ return address;
+ }
+
+ *relp = relation;
+ return address;
+}
+
+/*
+ * Find the ObjectAddress for a default ACL.
+ */
+static ObjectAddress
+get_object_address_defacl(List *object, bool missing_ok)
+{
+ HeapTuple tp;
+ Oid userid;
+ Oid schemaid;
+ char *username;
+ char *schema;
+ char objtype;
+ char *objtype_str;
+ ObjectAddress address;
+
+ ObjectAddressSet(address, DefaultAclRelationId, InvalidOid);
+
+ /*
+ * First figure out the textual attributes so that they can be used for
+ * error reporting.
+ */
+ username = strVal(lsecond(object));
+ if (list_length(object) >= 3)
+ schema = (char *) strVal(lthird(object));
+ else
+ schema = NULL;
+
+ /*
+ * Decode defaclobjtype. Only first char is considered; the rest of the
+ * string, if any, is blissfully ignored.
+ */
+ objtype = ((char *) strVal(linitial(object)))[0];
+ switch (objtype)
+ {
+ case DEFACLOBJ_RELATION:
+ objtype_str = "tables";
+ break;
+ case DEFACLOBJ_SEQUENCE:
+ objtype_str = "sequences";
+ break;
+ case DEFACLOBJ_FUNCTION:
+ objtype_str = "functions";
+ break;
+ case DEFACLOBJ_TYPE:
+ objtype_str = "types";
+ break;
+ case DEFACLOBJ_NAMESPACE:
+ objtype_str = "schemas";
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unrecognized default ACL object type \"%c\"", objtype),
+ errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".",
+ DEFACLOBJ_RELATION,
+ DEFACLOBJ_SEQUENCE,
+ DEFACLOBJ_FUNCTION,
+ DEFACLOBJ_TYPE,
+ DEFACLOBJ_NAMESPACE)));
+ }
+
+ /*
+ * Look up user ID. Behave as "default ACL not found" if the user doesn't
+ * exist.
+ */
+ tp = SearchSysCache1(AUTHNAME,
+ CStringGetDatum(username));
+ if (!HeapTupleIsValid(tp))
+ goto not_found;
+ userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
+ ReleaseSysCache(tp);
+
+ /*
+ * If a schema name was given, look up its OID. If it doesn't exist,
+ * behave as "default ACL not found".
+ */
+ if (schema)
+ {
+ schemaid = get_namespace_oid(schema, true);
+ if (schemaid == InvalidOid)
+ goto not_found;
+ }
+ else
+ schemaid = InvalidOid;
+
+ /* Finally, look up the pg_default_acl object */
+ tp = SearchSysCache3(DEFACLROLENSPOBJ,
+ ObjectIdGetDatum(userid),
+ ObjectIdGetDatum(schemaid),
+ CharGetDatum(objtype));
+ if (!HeapTupleIsValid(tp))
+ goto not_found;
+
+ address.objectId = ((Form_pg_default_acl) GETSTRUCT(tp))->oid;
+ ReleaseSysCache(tp);
+
+ return address;
+
+not_found:
+ if (!missing_ok)
+ {
+ if (schema)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("default ACL for user \"%s\" in schema \"%s\" on %s does not exist",
+ username, schema, objtype_str)));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("default ACL for user \"%s\" on %s does not exist",
+ username, objtype_str)));
+ }
+ return address;
+}
+
+/*
+ * Convert an array of TEXT into a List of string Values, as emitted by the
+ * parser, which is what get_object_address uses as input.
+ */
+static List *
+textarray_to_strvaluelist(ArrayType *arr)
+{
+ Datum *elems;
+ bool *nulls;
+ int nelems;
+ List *list = NIL;
+ int i;
+
+ deconstruct_array(arr, TEXTOID, -1, false, TYPALIGN_INT,
+ &elems, &nulls, &nelems);
+
+ for (i = 0; i < nelems; i++)
+ {
+ if (nulls[i])
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name or argument lists may not contain nulls")));
+ list = lappend(list, makeString(TextDatumGetCString(elems[i])));
+ }
+
+ return list;
+}
+
+/*
+ * SQL-callable version of get_object_address
+ */
+Datum
+pg_get_object_address(PG_FUNCTION_ARGS)
+{
+ char *ttype = TextDatumGetCString(PG_GETARG_DATUM(0));
+ ArrayType *namearr = PG_GETARG_ARRAYTYPE_P(1);
+ ArrayType *argsarr = PG_GETARG_ARRAYTYPE_P(2);
+ int itype;
+ ObjectType type;
+ List *name = NIL;
+ TypeName *typename = NULL;
+ List *args = NIL;
+ Node *objnode = NULL;
+ ObjectAddress addr;
+ TupleDesc tupdesc;
+ Datum values[3];
+ bool nulls[3];
+ HeapTuple htup;
+ Relation relation;
+
+ /* Decode object type, raise error if unknown */
+ itype = read_objtype_from_string(ttype);
+ if (itype < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unsupported object type \"%s\"", ttype)));
+ type = (ObjectType) itype;
+
+ /*
+ * Convert the text array to the representation appropriate for the given
+ * object type. Most use a simple string Values list, but there are some
+ * exceptions.
+ */
+ if (type == OBJECT_TYPE || type == OBJECT_DOMAIN || type == OBJECT_CAST ||
+ type == OBJECT_TRANSFORM || type == OBJECT_DOMCONSTRAINT)
+ {
+ Datum *elems;
+ bool *nulls;
+ int nelems;
+
+ deconstruct_array(namearr, TEXTOID, -1, false, TYPALIGN_INT,
+ &elems, &nulls, &nelems);
+ if (nelems != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name list length must be exactly %d", 1)));
+ if (nulls[0])
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name or argument lists may not contain nulls")));
+ typename = typeStringToTypeName(TextDatumGetCString(elems[0]));
+ }
+ else if (type == OBJECT_LARGEOBJECT)
+ {
+ Datum *elems;
+ bool *nulls;
+ int nelems;
+
+ deconstruct_array(namearr, TEXTOID, -1, false, TYPALIGN_INT,
+ &elems, &nulls, &nelems);
+ if (nelems != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name list length must be exactly %d", 1)));
+ if (nulls[0])
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("large object OID may not be null")));
+ objnode = (Node *) makeFloat(TextDatumGetCString(elems[0]));
+ }
+ else
+ {
+ name = textarray_to_strvaluelist(namearr);
+ if (list_length(name) < 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name list length must be at least %d", 1)));
+ }
+
+ /*
+ * If args are given, decode them according to the object type.
+ */
+ if (type == OBJECT_AGGREGATE ||
+ type == OBJECT_FUNCTION ||
+ type == OBJECT_PROCEDURE ||
+ type == OBJECT_ROUTINE ||
+ type == OBJECT_OPERATOR ||
+ type == OBJECT_CAST ||
+ type == OBJECT_AMOP ||
+ type == OBJECT_AMPROC)
+ {
+ /* in these cases, the args list must be of TypeName */
+ Datum *elems;
+ bool *nulls;
+ int nelems;
+ int i;
+
+ deconstruct_array(argsarr, TEXTOID, -1, false, TYPALIGN_INT,
+ &elems, &nulls, &nelems);
+
+ args = NIL;
+ for (i = 0; i < nelems; i++)
+ {
+ if (nulls[i])
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name or argument lists may not contain nulls")));
+ args = lappend(args,
+ typeStringToTypeName(TextDatumGetCString(elems[i])));
+ }
+ }
+ else
+ {
+ /* For all other object types, use string Values */
+ args = textarray_to_strvaluelist(argsarr);
+ }
+
+ /*
+ * get_object_address is pretty sensitive to the length of its input
+ * lists; check that they're what it wants.
+ */
+ switch (type)
+ {
+ case OBJECT_DOMCONSTRAINT:
+ case OBJECT_CAST:
+ case OBJECT_USER_MAPPING:
+ case OBJECT_PUBLICATION_REL:
+ case OBJECT_DEFACL:
+ case OBJECT_TRANSFORM:
+ if (list_length(args) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("argument list length must be exactly %d", 1)));
+ break;
+ case OBJECT_OPFAMILY:
+ case OBJECT_OPCLASS:
+ if (list_length(name) < 2)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name list length must be at least %d", 2)));
+ break;
+ case OBJECT_AMOP:
+ case OBJECT_AMPROC:
+ if (list_length(name) < 3)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name list length must be at least %d", 3)));
+ /* fall through to check args length */
+ /* FALLTHROUGH */
+ case OBJECT_OPERATOR:
+ if (list_length(args) != 2)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("argument list length must be exactly %d", 2)));
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Now build the Node type that get_object_address() expects for the given
+ * type.
+ */
+ switch (type)
+ {
+ case OBJECT_TABLE:
+ case OBJECT_SEQUENCE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_INDEX:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLUMN:
+ case OBJECT_ATTRIBUTE:
+ case OBJECT_COLLATION:
+ case OBJECT_CONVERSION:
+ case OBJECT_STATISTIC_EXT:
+ case OBJECT_TSPARSER:
+ case OBJECT_TSDICTIONARY:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_TSCONFIGURATION:
+ case OBJECT_DEFAULT:
+ case OBJECT_POLICY:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ case OBJECT_TABCONSTRAINT:
+ case OBJECT_OPCLASS:
+ case OBJECT_OPFAMILY:
+ objnode = (Node *) name;
+ break;
+ case OBJECT_ACCESS_METHOD:
+ case OBJECT_DATABASE:
+ case OBJECT_EVENT_TRIGGER:
+ case OBJECT_EXTENSION:
+ case OBJECT_FDW:
+ case OBJECT_FOREIGN_SERVER:
+ case OBJECT_LANGUAGE:
+ case OBJECT_PUBLICATION:
+ case OBJECT_ROLE:
+ case OBJECT_SCHEMA:
+ case OBJECT_SUBSCRIPTION:
+ case OBJECT_TABLESPACE:
+ if (list_length(name) != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("name list length must be exactly %d", 1)));
+ objnode = linitial(name);
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ objnode = (Node *) typename;
+ break;
+ case OBJECT_CAST:
+ case OBJECT_DOMCONSTRAINT:
+ case OBJECT_TRANSFORM:
+ objnode = (Node *) list_make2(typename, linitial(args));
+ break;
+ case OBJECT_PUBLICATION_REL:
+ objnode = (Node *) list_make2(name, linitial(args));
+ break;
+ case OBJECT_USER_MAPPING:
+ objnode = (Node *) list_make2(linitial(name), linitial(args));
+ break;
+ case OBJECT_DEFACL:
+ objnode = (Node *) lcons(linitial(args), name);
+ break;
+ case OBJECT_AMOP:
+ case OBJECT_AMPROC:
+ objnode = (Node *) list_make2(name, args);
+ break;
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ case OBJECT_AGGREGATE:
+ case OBJECT_OPERATOR:
+ {
+ ObjectWithArgs *owa = makeNode(ObjectWithArgs);
+
+ owa->objname = name;
+ owa->objargs = args;
+ objnode = (Node *) owa;
+ break;
+ }
+ case OBJECT_LARGEOBJECT:
+ /* already handled above */
+ break;
+ /* no default, to let compiler warn about missing case */
+ }
+
+ if (objnode == NULL)
+ elog(ERROR, "unrecognized object type: %d", type);
+
+ addr = get_object_address(type, objnode,
+ &relation, AccessShareLock, false);
+
+ /* We don't need the relcache entry, thank you very much */
+ if (relation)
+ relation_close(relation, AccessShareLock);
+
+ tupdesc = CreateTemplateTupleDesc(3);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "classid",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "objid",
+ OIDOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "objsubid",
+ INT4OID, -1, 0);
+ tupdesc = BlessTupleDesc(tupdesc);
+
+ values[0] = ObjectIdGetDatum(addr.classId);
+ values[1] = ObjectIdGetDatum(addr.objectId);
+ values[2] = Int32GetDatum(addr.objectSubId);
+ nulls[0] = false;
+ nulls[1] = false;
+ nulls[2] = false;
+
+ htup = heap_form_tuple(tupdesc, values, nulls);
+
+ PG_RETURN_DATUM(HeapTupleGetDatum(htup));
+}
+
+/*
+ * Check ownership of an object previously identified by get_object_address.
+ */
+void
+check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
+ Node *object, Relation relation)
+{
+ switch (objtype)
+ {
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_MATVIEW:
+ case OBJECT_FOREIGN_TABLE:
+ case OBJECT_COLUMN:
+ case OBJECT_RULE:
+ case OBJECT_TRIGGER:
+ case OBJECT_POLICY:
+ case OBJECT_TABCONSTRAINT:
+ if (!pg_class_ownercheck(RelationGetRelid(relation), roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ RelationGetRelationName(relation));
+ break;
+ case OBJECT_DATABASE:
+ if (!pg_database_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_TYPE:
+ case OBJECT_DOMAIN:
+ case OBJECT_ATTRIBUTE:
+ if (!pg_type_ownercheck(address.objectId, roleid))
+ aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
+ break;
+ case OBJECT_DOMCONSTRAINT:
+ {
+ HeapTuple tuple;
+ Oid contypid;
+
+ tuple = SearchSysCache1(CONSTROID,
+ ObjectIdGetDatum(address.objectId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "constraint with OID %u does not exist",
+ address.objectId);
+
+ contypid = ((Form_pg_constraint) GETSTRUCT(tuple))->contypid;
+
+ ReleaseSysCache(tuple);
+
+ /*
+ * Fallback to type ownership check in this case as this is
+ * what domain constraints rely on.
+ */
+ if (!pg_type_ownercheck(contypid, roleid))
+ aclcheck_error_type(ACLCHECK_NOT_OWNER, contypid);
+ }
+ break;
+ case OBJECT_AGGREGATE:
+ case OBJECT_FUNCTION:
+ case OBJECT_PROCEDURE:
+ case OBJECT_ROUTINE:
+ if (!pg_proc_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ NameListToString((castNode(ObjectWithArgs, object))->objname));
+ break;
+ case OBJECT_OPERATOR:
+ if (!pg_oper_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ NameListToString((castNode(ObjectWithArgs, object))->objname));
+ break;
+ case OBJECT_SCHEMA:
+ if (!pg_namespace_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_COLLATION:
+ if (!pg_collation_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ NameListToString(castNode(List, object)));
+ break;
+ case OBJECT_CONVERSION:
+ if (!pg_conversion_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ NameListToString(castNode(List, object)));
+ break;
+ case OBJECT_EXTENSION:
+ if (!pg_extension_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_FDW:
+ if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_FOREIGN_SERVER:
+ if (!pg_foreign_server_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_EVENT_TRIGGER:
+ if (!pg_event_trigger_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_LANGUAGE:
+ if (!pg_language_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_OPCLASS:
+ if (!pg_opclass_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ NameListToString(castNode(List, object)));
+ break;
+ case OBJECT_OPFAMILY:
+ if (!pg_opfamily_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ NameListToString(castNode(List, object)));
+ break;
+ case OBJECT_LARGEOBJECT:
+ if (!lo_compat_privileges &&
+ !pg_largeobject_ownercheck(address.objectId, roleid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be owner of large object %u",
+ address.objectId)));
+ break;
+ case OBJECT_CAST:
+ {
+ /* We can only check permissions on the source/target types */
+ TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
+ TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
+ Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
+ Oid targettypeid = typenameTypeId(NULL, targettype);
+
+ if (!pg_type_ownercheck(sourcetypeid, roleid)
+ && !pg_type_ownercheck(targettypeid, roleid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be owner of type %s or type %s",
+ format_type_be(sourcetypeid),
+ format_type_be(targettypeid))));
+ }
+ break;
+ case OBJECT_PUBLICATION:
+ if (!pg_publication_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_SUBSCRIPTION:
+ if (!pg_subscription_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_TRANSFORM:
+ {
+ TypeName *typename = linitial_node(TypeName, castNode(List, object));
+ Oid typeid = typenameTypeId(NULL, typename);
+
+ if (!pg_type_ownercheck(typeid, roleid))
+ aclcheck_error_type(ACLCHECK_NOT_OWNER, typeid);
+ }
+ break;
+ case OBJECT_TABLESPACE:
+ if (!pg_tablespace_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ strVal((Value *) object));
+ break;
+ case OBJECT_TSDICTIONARY:
+ if (!pg_ts_dict_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ NameListToString(castNode(List, object)));
+ break;
+ case OBJECT_TSCONFIGURATION:
+ if (!pg_ts_config_ownercheck(address.objectId, roleid))
+ aclcheck_error(ACLCHECK_NOT_OWNER, objtype,
+ NameListToString(castNode(List, object)));
+ break;
+ case OBJECT_ROLE:
+
+ /*
+ * We treat roles as being "owned" by those with CREATEROLE priv,
+ * except that superusers are only owned by superusers.
+ */
+ if (superuser_arg(address.objectId))
+ {
+ if (!superuser_arg(roleid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser")));
+ }
+ else
+ {
+ if (!has_createrole_privilege(roleid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must have CREATEROLE privilege")));
+ }
+ break;
+ case OBJECT_TSPARSER:
+ case OBJECT_TSTEMPLATE:
+ case OBJECT_ACCESS_METHOD:
+ /* We treat these object types as being owned by superusers */
+ if (!superuser_arg(roleid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("must be superuser")));
+ break;
+ case OBJECT_STATISTIC_EXT:
+ if (!pg_statistics_object_ownercheck(address.objectId, roleid))
+ aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId);
+ break;
+ default:
+ elog(ERROR, "unrecognized object type: %d",
+ (int) objtype);
+ }
+}
+
+/*
+ * get_object_namespace
+ *
+ * Find the schema containing the specified object. For non-schema objects,
+ * this function returns InvalidOid.
+ */
+Oid
+get_object_namespace(const ObjectAddress *address)
+{
+ int cache;
+ HeapTuple tuple;
+ bool isnull;
+ Oid oid;
+ const ObjectPropertyType *property;
+
+ /* If not owned by a namespace, just return InvalidOid. */
+ property = get_object_property_data(address->classId);
+ if (property->attnum_namespace == InvalidAttrNumber)
+ return InvalidOid;
+
+ /* Currently, we can only handle object types with system caches. */
+ cache = property->oid_catcache_id;
+ Assert(cache != -1);
+
+ /* Fetch tuple from syscache and extract namespace attribute. */
+ tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for cache %d oid %u",
+ cache, address->objectId);
+ oid = DatumGetObjectId(SysCacheGetAttr(cache,
+ tuple,
+ property->attnum_namespace,
+ &isnull));
+ Assert(!isnull);
+ ReleaseSysCache(tuple);
+
+ return oid;
+}
+
+/*
+ * Return ObjectType for the given object type as given by
+ * getObjectTypeDescription; if no valid ObjectType code exists, but it's a
+ * possible output type from getObjectTypeDescription, return -1.
+ * Otherwise, an error is thrown.
+ */
+int
+read_objtype_from_string(const char *objtype)
+{
+ int i;
+
+ for (i = 0; i < lengthof(ObjectTypeMap); i++)
+ {
+ if (strcmp(ObjectTypeMap[i].tm_name, objtype) == 0)
+ return ObjectTypeMap[i].tm_type;
+ }
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unrecognized object type \"%s\"", objtype)));
+
+ return -1; /* keep compiler quiet */
+}
+
+/*
+ * Interfaces to reference fields of ObjectPropertyType
+ */
+Oid
+get_object_oid_index(Oid class_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ return prop->oid_index_oid;
+}
+
+int
+get_object_catcache_oid(Oid class_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ return prop->oid_catcache_id;
+}
+
+int
+get_object_catcache_name(Oid class_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ return prop->name_catcache_id;
+}
+
+AttrNumber
+get_object_attnum_oid(Oid class_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ return prop->attnum_oid;
+}
+
+AttrNumber
+get_object_attnum_name(Oid class_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ return prop->attnum_name;
+}
+
+AttrNumber
+get_object_attnum_namespace(Oid class_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ return prop->attnum_namespace;
+}
+
+AttrNumber
+get_object_attnum_owner(Oid class_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ return prop->attnum_owner;
+}
+
+AttrNumber
+get_object_attnum_acl(Oid class_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ return prop->attnum_acl;
+}
+
+/*
+ * get_object_type
+ *
+ * Return the object type associated with a given object. This routine
+ * is primarily used to determine the object type to mention in ACL check
+ * error messages, so it's desirable for it to avoid failing.
+ */
+ObjectType
+get_object_type(Oid class_id, Oid object_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ if (prop->objtype == OBJECT_TABLE)
+ {
+ /*
+ * If the property data says it's a table, dig a little deeper to get
+ * the real relation kind, so that callers can produce more precise
+ * error messages.
+ */
+ return get_relkind_objtype(get_rel_relkind(object_id));
+ }
+ else
+ return prop->objtype;
+}
+
+bool
+get_object_namensp_unique(Oid class_id)
+{
+ const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+ return prop->is_nsp_name_unique;
+}
+
+/*
+ * Return whether we have useful data for the given object class in the
+ * ObjectProperty table.
+ */
+bool
+is_objectclass_supported(Oid class_id)
+{
+ int index;
+
+ for (index = 0; index < lengthof(ObjectProperty); index++)
+ {
+ if (ObjectProperty[index].class_oid == class_id)
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Find ObjectProperty structure by class_id.
+ */
+static const ObjectPropertyType *
+get_object_property_data(Oid class_id)
+{
+ static const ObjectPropertyType *prop_last = NULL;
+ int index;
+
+ /*
+ * A shortcut to speed up multiple consecutive lookups of a particular
+ * object class.
+ */
+ if (prop_last && prop_last->class_oid == class_id)
+ return prop_last;
+
+ for (index = 0; index < lengthof(ObjectProperty); index++)
+ {
+ if (ObjectProperty[index].class_oid == class_id)
+ {
+ prop_last = &ObjectProperty[index];
+ return &ObjectProperty[index];
+ }
+ }
+
+ ereport(ERROR,
+ (errmsg_internal("unrecognized class ID: %u", class_id)));
+
+ return NULL; /* keep MSC compiler happy */
+}
+
+/*
+ * Return a copy of the tuple for the object with the given object OID, from
+ * the given catalog (which must have been opened by the caller and suitably
+ * locked). NULL is returned if the OID is not found.
+ *
+ * We try a syscache first, if available.
+ */
+HeapTuple
+get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId)
+{
+ HeapTuple tuple;
+ Oid classId = RelationGetRelid(catalog);
+ int oidCacheId = get_object_catcache_oid(classId);
+
+ if (oidCacheId > 0)
+ {
+ tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId));
+ if (!HeapTupleIsValid(tuple)) /* should not happen */
+ return NULL;
+ }
+ else
+ {
+ Oid oidIndexId = get_object_oid_index(classId);
+ SysScanDesc scan;
+ ScanKeyData skey;
+
+ Assert(OidIsValid(oidIndexId));
+
+ ScanKeyInit(&skey,
+ oidcol,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(catalog, oidIndexId, true,
+ NULL, 1, &skey);
+ tuple = systable_getnext(scan);
+ if (!HeapTupleIsValid(tuple))
+ {
+ systable_endscan(scan);
+ return NULL;
+ }
+ tuple = heap_copytuple(tuple);
+
+ systable_endscan(scan);
+ }
+
+ return tuple;
+}
+
+/*
+ * getObjectDescription: build an object description for messages
+ *
+ * The result is a palloc'd string.
+ */
+char *
+getObjectDescription(const ObjectAddress *object)
+{
+ StringInfoData buffer;
+
+ initStringInfo(&buffer);
+
+ switch (getObjectClass(object))
+ {
+ case OCLASS_CLASS:
+ if (object->objectSubId == 0)
+ getRelationDescription(&buffer, object->objectId);
+ else
+ {
+ /* column, not whole relation */
+ StringInfoData rel;
+
+ initStringInfo(&rel);
+ getRelationDescription(&rel, object->objectId);
+ /* translator: second %s is, e.g., "table %s" */
+ appendStringInfo(&buffer, _("column %s of %s"),
+ get_attname(object->objectId,
+ object->objectSubId,
+ false),
+ rel.data);
+ pfree(rel.data);
+ }
+ break;
+
+ case OCLASS_PROC:
+ appendStringInfo(&buffer, _("function %s"),
+ format_procedure(object->objectId));
+ break;
+
+ case OCLASS_TYPE:
+ appendStringInfo(&buffer, _("type %s"),
+ format_type_be(object->objectId));
+ break;
+
+ case OCLASS_CAST:
+ {
+ Relation castDesc;
+ ScanKeyData skey[1];
+ SysScanDesc rcscan;
+ HeapTuple tup;
+ Form_pg_cast castForm;
+
+ castDesc = table_open(CastRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_cast_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ rcscan = systable_beginscan(castDesc, CastOidIndexId, true,
+ NULL, 1, skey);
+
+ tup = systable_getnext(rcscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for cast %u",
+ object->objectId);
+
+ castForm = (Form_pg_cast) GETSTRUCT(tup);
+
+ appendStringInfo(&buffer, _("cast from %s to %s"),
+ format_type_be(castForm->castsource),
+ format_type_be(castForm->casttarget));
+
+ systable_endscan(rcscan);
+ table_close(castDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_COLLATION:
+ {
+ HeapTuple collTup;
+ Form_pg_collation coll;
+ char *nspname;
+
+ collTup = SearchSysCache1(COLLOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(collTup))
+ elog(ERROR, "cache lookup failed for collation %u",
+ object->objectId);
+ coll = (Form_pg_collation) GETSTRUCT(collTup);
+
+ /* Qualify the name if not visible in search path */
+ if (CollationIsVisible(object->objectId))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(coll->collnamespace);
+
+ appendStringInfo(&buffer, _("collation %s"),
+ quote_qualified_identifier(nspname,
+ NameStr(coll->collname)));
+ ReleaseSysCache(collTup);
+ break;
+ }
+
+ case OCLASS_CONSTRAINT:
+ {
+ HeapTuple conTup;
+ Form_pg_constraint con;
+
+ conTup = SearchSysCache1(CONSTROID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(conTup))
+ elog(ERROR, "cache lookup failed for constraint %u",
+ object->objectId);
+ con = (Form_pg_constraint) GETSTRUCT(conTup);
+
+ if (OidIsValid(con->conrelid))
+ {
+ StringInfoData rel;
+
+ initStringInfo(&rel);
+ getRelationDescription(&rel, con->conrelid);
+ /* translator: second %s is, e.g., "table %s" */
+ appendStringInfo(&buffer, _("constraint %s on %s"),
+ NameStr(con->conname), rel.data);
+ pfree(rel.data);
+ }
+ else
+ {
+ appendStringInfo(&buffer, _("constraint %s"),
+ NameStr(con->conname));
+ }
+
+ ReleaseSysCache(conTup);
+ break;
+ }
+
+ case OCLASS_CONVERSION:
+ {
+ HeapTuple conTup;
+ Form_pg_conversion conv;
+ char *nspname;
+
+ conTup = SearchSysCache1(CONVOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(conTup))
+ elog(ERROR, "cache lookup failed for conversion %u",
+ object->objectId);
+ conv = (Form_pg_conversion) GETSTRUCT(conTup);
+
+ /* Qualify the name if not visible in search path */
+ if (ConversionIsVisible(object->objectId))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(conv->connamespace);
+
+ appendStringInfo(&buffer, _("conversion %s"),
+ quote_qualified_identifier(nspname,
+ NameStr(conv->conname)));
+ ReleaseSysCache(conTup);
+ break;
+ }
+
+ case OCLASS_DEFAULT:
+ {
+ Relation attrdefDesc;
+ ScanKeyData skey[1];
+ SysScanDesc adscan;
+ HeapTuple tup;
+ Form_pg_attrdef attrdef;
+ ObjectAddress colobject;
+
+ attrdefDesc = table_open(AttrDefaultRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_attrdef_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndexId,
+ true, NULL, 1, skey);
+
+ tup = systable_getnext(adscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for attrdef %u",
+ object->objectId);
+
+ attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
+
+ colobject.classId = RelationRelationId;
+ colobject.objectId = attrdef->adrelid;
+ colobject.objectSubId = attrdef->adnum;
+
+ /* translator: %s is typically "column %s of table %s" */
+ appendStringInfo(&buffer, _("default value for %s"),
+ getObjectDescription(&colobject));
+
+ systable_endscan(adscan);
+ table_close(attrdefDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_LANGUAGE:
+ appendStringInfo(&buffer, _("language %s"),
+ get_language_name(object->objectId, false));
+ break;
+
+ case OCLASS_LARGEOBJECT:
+ appendStringInfo(&buffer, _("large object %u"),
+ object->objectId);
+ break;
+
+ case OCLASS_OPERATOR:
+ appendStringInfo(&buffer, _("operator %s"),
+ format_operator(object->objectId));
+ break;
+
+ case OCLASS_OPCLASS:
+ {
+ HeapTuple opcTup;
+ Form_pg_opclass opcForm;
+ HeapTuple amTup;
+ Form_pg_am amForm;
+ char *nspname;
+
+ opcTup = SearchSysCache1(CLAOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(opcTup))
+ elog(ERROR, "cache lookup failed for opclass %u",
+ object->objectId);
+ opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
+
+ amTup = SearchSysCache1(AMOID,
+ ObjectIdGetDatum(opcForm->opcmethod));
+ if (!HeapTupleIsValid(amTup))
+ elog(ERROR, "cache lookup failed for access method %u",
+ opcForm->opcmethod);
+ amForm = (Form_pg_am) GETSTRUCT(amTup);
+
+ /* Qualify the name if not visible in search path */
+ if (OpclassIsVisible(object->objectId))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(opcForm->opcnamespace);
+
+ appendStringInfo(&buffer, _("operator class %s for access method %s"),
+ quote_qualified_identifier(nspname,
+ NameStr(opcForm->opcname)),
+ NameStr(amForm->amname));
+
+ ReleaseSysCache(amTup);
+ ReleaseSysCache(opcTup);
+ break;
+ }
+
+ case OCLASS_OPFAMILY:
+ getOpFamilyDescription(&buffer, object->objectId);
+ break;
+
+ case OCLASS_AM:
+ {
+ HeapTuple tup;
+
+ tup = SearchSysCache1(AMOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for access method %u",
+ object->objectId);
+ appendStringInfo(&buffer, _("access method %s"),
+ NameStr(((Form_pg_am) GETSTRUCT(tup))->amname));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_AMOP:
+ {
+ Relation amopDesc;
+ HeapTuple tup;
+ ScanKeyData skey[1];
+ SysScanDesc amscan;
+ Form_pg_amop amopForm;
+ StringInfoData opfam;
+
+ amopDesc = table_open(AccessMethodOperatorRelationId,
+ AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_amop_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
+ NULL, 1, skey);
+
+ tup = systable_getnext(amscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for amop entry %u",
+ object->objectId);
+
+ amopForm = (Form_pg_amop) GETSTRUCT(tup);
+
+ initStringInfo(&opfam);
+ getOpFamilyDescription(&opfam, amopForm->amopfamily);
+
+ /*------
+ translator: %d is the operator strategy (a number), the
+ first two %s's are data type names, the third %s is the
+ description of the operator family, and the last %s is the
+ textual form of the operator with arguments. */
+ appendStringInfo(&buffer, _("operator %d (%s, %s) of %s: %s"),
+ amopForm->amopstrategy,
+ format_type_be(amopForm->amoplefttype),
+ format_type_be(amopForm->amoprighttype),
+ opfam.data,
+ format_operator(amopForm->amopopr));
+
+ pfree(opfam.data);
+
+ systable_endscan(amscan);
+ table_close(amopDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_AMPROC:
+ {
+ Relation amprocDesc;
+ ScanKeyData skey[1];
+ SysScanDesc amscan;
+ HeapTuple tup;
+ Form_pg_amproc amprocForm;
+ StringInfoData opfam;
+
+ amprocDesc = table_open(AccessMethodProcedureRelationId,
+ AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_amproc_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ amscan = systable_beginscan(amprocDesc, AccessMethodProcedureOidIndexId, true,
+ NULL, 1, skey);
+
+ tup = systable_getnext(amscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for amproc entry %u",
+ object->objectId);
+
+ amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
+
+ initStringInfo(&opfam);
+ getOpFamilyDescription(&opfam, amprocForm->amprocfamily);
+
+ /*------
+ translator: %d is the function number, the first two %s's
+ are data type names, the third %s is the description of the
+ operator family, and the last %s is the textual form of the
+ function with arguments. */
+ appendStringInfo(&buffer, _("function %d (%s, %s) of %s: %s"),
+ amprocForm->amprocnum,
+ format_type_be(amprocForm->amproclefttype),
+ format_type_be(amprocForm->amprocrighttype),
+ opfam.data,
+ format_procedure(amprocForm->amproc));
+
+ pfree(opfam.data);
+
+ systable_endscan(amscan);
+ table_close(amprocDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_REWRITE:
+ {
+ Relation ruleDesc;
+ ScanKeyData skey[1];
+ SysScanDesc rcscan;
+ HeapTuple tup;
+ Form_pg_rewrite rule;
+ StringInfoData rel;
+
+ ruleDesc = table_open(RewriteRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_rewrite_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ rcscan = systable_beginscan(ruleDesc, RewriteOidIndexId, true,
+ NULL, 1, skey);
+
+ tup = systable_getnext(rcscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for rule %u",
+ object->objectId);
+ rule = (Form_pg_rewrite) GETSTRUCT(tup);
+
+ initStringInfo(&rel);
+ getRelationDescription(&rel, rule->ev_class);
+
+ /* translator: second %s is, e.g., "table %s" */
+ appendStringInfo(&buffer, _("rule %s on %s"),
+ NameStr(rule->rulename), rel.data);
+ pfree(rel.data);
+ systable_endscan(rcscan);
+ table_close(ruleDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_TRIGGER:
+ {
+ Relation trigDesc;
+ ScanKeyData skey[1];
+ SysScanDesc tgscan;
+ HeapTuple tup;
+ Form_pg_trigger trig;
+ StringInfoData rel;
+
+ trigDesc = table_open(TriggerRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_trigger_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ tgscan = systable_beginscan(trigDesc, TriggerOidIndexId, true,
+ NULL, 1, skey);
+
+ tup = systable_getnext(tgscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for trigger %u",
+ object->objectId);
+ trig = (Form_pg_trigger) GETSTRUCT(tup);
+
+ initStringInfo(&rel);
+ getRelationDescription(&rel, trig->tgrelid);
+
+ /* translator: second %s is, e.g., "table %s" */
+ appendStringInfo(&buffer, _("trigger %s on %s"),
+ NameStr(trig->tgname), rel.data);
+ pfree(rel.data);
+ systable_endscan(tgscan);
+ table_close(trigDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_SCHEMA:
+ {
+ char *nspname;
+
+ nspname = get_namespace_name(object->objectId);
+ if (!nspname)
+ elog(ERROR, "cache lookup failed for namespace %u",
+ object->objectId);
+ appendStringInfo(&buffer, _("schema %s"), nspname);
+ break;
+ }
+
+ case OCLASS_STATISTIC_EXT:
+ {
+ HeapTuple stxTup;
+ Form_pg_statistic_ext stxForm;
+ char *nspname;
+
+ stxTup = SearchSysCache1(STATEXTOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(stxTup))
+ elog(ERROR, "could not find tuple for statistics object %u",
+ object->objectId);
+ stxForm = (Form_pg_statistic_ext) GETSTRUCT(stxTup);
+
+ /* Qualify the name if not visible in search path */
+ if (StatisticsObjIsVisible(object->objectId))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(stxForm->stxnamespace);
+
+ appendStringInfo(&buffer, _("statistics object %s"),
+ quote_qualified_identifier(nspname,
+ NameStr(stxForm->stxname)));
+
+ ReleaseSysCache(stxTup);
+ break;
+ }
+
+ case OCLASS_TSPARSER:
+ {
+ HeapTuple tup;
+ Form_pg_ts_parser prsForm;
+ char *nspname;
+
+ tup = SearchSysCache1(TSPARSEROID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search parser %u",
+ object->objectId);
+ prsForm = (Form_pg_ts_parser) GETSTRUCT(tup);
+
+ /* Qualify the name if not visible in search path */
+ if (TSParserIsVisible(object->objectId))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(prsForm->prsnamespace);
+
+ appendStringInfo(&buffer, _("text search parser %s"),
+ quote_qualified_identifier(nspname,
+ NameStr(prsForm->prsname)));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_TSDICT:
+ {
+ HeapTuple tup;
+ Form_pg_ts_dict dictForm;
+ char *nspname;
+
+ tup = SearchSysCache1(TSDICTOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search dictionary %u",
+ object->objectId);
+ dictForm = (Form_pg_ts_dict) GETSTRUCT(tup);
+
+ /* Qualify the name if not visible in search path */
+ if (TSDictionaryIsVisible(object->objectId))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(dictForm->dictnamespace);
+
+ appendStringInfo(&buffer, _("text search dictionary %s"),
+ quote_qualified_identifier(nspname,
+ NameStr(dictForm->dictname)));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_TSTEMPLATE:
+ {
+ HeapTuple tup;
+ Form_pg_ts_template tmplForm;
+ char *nspname;
+
+ tup = SearchSysCache1(TSTEMPLATEOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search template %u",
+ object->objectId);
+ tmplForm = (Form_pg_ts_template) GETSTRUCT(tup);
+
+ /* Qualify the name if not visible in search path */
+ if (TSTemplateIsVisible(object->objectId))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(tmplForm->tmplnamespace);
+
+ appendStringInfo(&buffer, _("text search template %s"),
+ quote_qualified_identifier(nspname,
+ NameStr(tmplForm->tmplname)));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_TSCONFIG:
+ {
+ HeapTuple tup;
+ Form_pg_ts_config cfgForm;
+ char *nspname;
+
+ tup = SearchSysCache1(TSCONFIGOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search configuration %u",
+ object->objectId);
+ cfgForm = (Form_pg_ts_config) GETSTRUCT(tup);
+
+ /* Qualify the name if not visible in search path */
+ if (TSConfigIsVisible(object->objectId))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(cfgForm->cfgnamespace);
+
+ appendStringInfo(&buffer, _("text search configuration %s"),
+ quote_qualified_identifier(nspname,
+ NameStr(cfgForm->cfgname)));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_ROLE:
+ {
+ appendStringInfo(&buffer, _("role %s"),
+ GetUserNameFromId(object->objectId, false));
+ break;
+ }
+
+ case OCLASS_DATABASE:
+ {
+ char *datname;
+
+ datname = get_database_name(object->objectId);
+ if (!datname)
+ elog(ERROR, "cache lookup failed for database %u",
+ object->objectId);
+ appendStringInfo(&buffer, _("database %s"), datname);
+ break;
+ }
+
+ case OCLASS_TBLSPACE:
+ {
+ char *tblspace;
+
+ tblspace = get_tablespace_name(object->objectId);
+ if (!tblspace)
+ elog(ERROR, "cache lookup failed for tablespace %u",
+ object->objectId);
+ appendStringInfo(&buffer, _("tablespace %s"), tblspace);
+ break;
+ }
+
+ case OCLASS_FDW:
+ {
+ ForeignDataWrapper *fdw;
+
+ fdw = GetForeignDataWrapper(object->objectId);
+ appendStringInfo(&buffer, _("foreign-data wrapper %s"), fdw->fdwname);
+ break;
+ }
+
+ case OCLASS_FOREIGN_SERVER:
+ {
+ ForeignServer *srv;
+
+ srv = GetForeignServer(object->objectId);
+ appendStringInfo(&buffer, _("server %s"), srv->servername);
+ break;
+ }
+
+ case OCLASS_USER_MAPPING:
+ {
+ HeapTuple tup;
+ Oid useid;
+ char *usename;
+ Form_pg_user_mapping umform;
+ ForeignServer *srv;
+
+ tup = SearchSysCache1(USERMAPPINGOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for user mapping %u",
+ object->objectId);
+ umform = (Form_pg_user_mapping) GETSTRUCT(tup);
+ useid = umform->umuser;
+ srv = GetForeignServer(umform->umserver);
+
+ ReleaseSysCache(tup);
+
+ if (OidIsValid(useid))
+ usename = GetUserNameFromId(useid, false);
+ else
+ usename = "public";
+
+ appendStringInfo(&buffer, _("user mapping for %s on server %s"), usename,
+ srv->servername);
+ break;
+ }
+
+ case OCLASS_DEFACL:
+ {
+ Relation defaclrel;
+ ScanKeyData skey[1];
+ SysScanDesc rcscan;
+ HeapTuple tup;
+ Form_pg_default_acl defacl;
+ char *rolename;
+ char *nspname;
+
+ defaclrel = table_open(DefaultAclRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_default_acl_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ rcscan = systable_beginscan(defaclrel, DefaultAclOidIndexId,
+ true, NULL, 1, skey);
+
+ tup = systable_getnext(rcscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for default ACL %u",
+ object->objectId);
+
+ defacl = (Form_pg_default_acl) GETSTRUCT(tup);
+
+ rolename = GetUserNameFromId(defacl->defaclrole, false);
+
+ if (OidIsValid(defacl->defaclnamespace))
+ nspname = get_namespace_name(defacl->defaclnamespace);
+ else
+ nspname = NULL;
+
+ switch (defacl->defaclobjtype)
+ {
+ case DEFACLOBJ_RELATION:
+ if (nspname)
+ appendStringInfo(&buffer,
+ _("default privileges on new relations belonging to role %s in schema %s"),
+ rolename, nspname);
+ else
+ appendStringInfo(&buffer,
+ _("default privileges on new relations belonging to role %s"),
+ rolename);
+ break;
+ case DEFACLOBJ_SEQUENCE:
+ if (nspname)
+ appendStringInfo(&buffer,
+ _("default privileges on new sequences belonging to role %s in schema %s"),
+ rolename, nspname);
+ else
+ appendStringInfo(&buffer,
+ _("default privileges on new sequences belonging to role %s"),
+ rolename);
+ break;
+ case DEFACLOBJ_FUNCTION:
+ if (nspname)
+ appendStringInfo(&buffer,
+ _("default privileges on new functions belonging to role %s in schema %s"),
+ rolename, nspname);
+ else
+ appendStringInfo(&buffer,
+ _("default privileges on new functions belonging to role %s"),
+ rolename);
+ break;
+ case DEFACLOBJ_TYPE:
+ if (nspname)
+ appendStringInfo(&buffer,
+ _("default privileges on new types belonging to role %s in schema %s"),
+ rolename, nspname);
+ else
+ appendStringInfo(&buffer,
+ _("default privileges on new types belonging to role %s"),
+ rolename);
+ break;
+ case DEFACLOBJ_NAMESPACE:
+ Assert(!nspname);
+ appendStringInfo(&buffer,
+ _("default privileges on new schemas belonging to role %s"),
+ rolename);
+ break;
+ default:
+ /* shouldn't get here */
+ if (nspname)
+ appendStringInfo(&buffer,
+ _("default privileges belonging to role %s in schema %s"),
+ rolename, nspname);
+ else
+ appendStringInfo(&buffer,
+ _("default privileges belonging to role %s"),
+ rolename);
+ break;
+ }
+
+ systable_endscan(rcscan);
+ table_close(defaclrel, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_EXTENSION:
+ {
+ char *extname;
+
+ extname = get_extension_name(object->objectId);
+ if (!extname)
+ elog(ERROR, "cache lookup failed for extension %u",
+ object->objectId);
+ appendStringInfo(&buffer, _("extension %s"), extname);
+ break;
+ }
+
+ case OCLASS_EVENT_TRIGGER:
+ {
+ HeapTuple tup;
+
+ tup = SearchSysCache1(EVENTTRIGGEROID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for event trigger %u",
+ object->objectId);
+ appendStringInfo(&buffer, _("event trigger %s"),
+ NameStr(((Form_pg_event_trigger) GETSTRUCT(tup))->evtname));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_POLICY:
+ {
+ Relation policy_rel;
+ ScanKeyData skey[1];
+ SysScanDesc sscan;
+ HeapTuple tuple;
+ Form_pg_policy form_policy;
+ StringInfoData rel;
+
+ policy_rel = table_open(PolicyRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_policy_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ sscan = systable_beginscan(policy_rel, PolicyOidIndexId,
+ true, NULL, 1, skey);
+
+ tuple = systable_getnext(sscan);
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "could not find tuple for policy %u",
+ object->objectId);
+ form_policy = (Form_pg_policy) GETSTRUCT(tuple);
+
+ initStringInfo(&rel);
+ getRelationDescription(&rel, form_policy->polrelid);
+
+ /* translator: second %s is, e.g., "table %s" */
+ appendStringInfo(&buffer, _("policy %s on %s"),
+ NameStr(form_policy->polname), rel.data);
+ pfree(rel.data);
+ systable_endscan(sscan);
+ table_close(policy_rel, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_PUBLICATION:
+ {
+ appendStringInfo(&buffer, _("publication %s"),
+ get_publication_name(object->objectId,
+ false));
+ break;
+ }
+
+ case OCLASS_PUBLICATION_REL:
+ {
+ HeapTuple tup;
+ char *pubname;
+ Form_pg_publication_rel prform;
+ StringInfoData rel;
+
+ tup = SearchSysCache1(PUBLICATIONREL,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for publication table %u",
+ object->objectId);
+
+ prform = (Form_pg_publication_rel) GETSTRUCT(tup);
+ pubname = get_publication_name(prform->prpubid, false);
+
+ initStringInfo(&rel);
+ getRelationDescription(&rel, prform->prrelid);
+
+ /* translator: first %s is, e.g., "table %s" */
+ appendStringInfo(&buffer, _("publication of %s in publication %s"),
+ rel.data, pubname);
+ pfree(rel.data);
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_SUBSCRIPTION:
+ {
+ appendStringInfo(&buffer, _("subscription %s"),
+ get_subscription_name(object->objectId,
+ false));
+ break;
+ }
+
+ case OCLASS_TRANSFORM:
+ {
+ HeapTuple trfTup;
+ Form_pg_transform trfForm;
+
+ trfTup = SearchSysCache1(TRFOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(trfTup))
+ elog(ERROR, "could not find tuple for transform %u",
+ object->objectId);
+
+ trfForm = (Form_pg_transform) GETSTRUCT(trfTup);
+
+ appendStringInfo(&buffer, _("transform for %s language %s"),
+ format_type_be(trfForm->trftype),
+ get_language_name(trfForm->trflang, false));
+
+ ReleaseSysCache(trfTup);
+ break;
+ }
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
+ }
+
+ return buffer.data;
+}
+
+/*
+ * getObjectDescriptionOids: as above, except the object is specified by Oids
+ */
+char *
+getObjectDescriptionOids(Oid classid, Oid objid)
+{
+ ObjectAddress address;
+
+ address.classId = classid;
+ address.objectId = objid;
+ address.objectSubId = 0;
+
+ return getObjectDescription(&address);
+}
+
+/*
+ * subroutine for getObjectDescription: describe a relation
+ *
+ * The result is appended to "buffer".
+ */
+static void
+getRelationDescription(StringInfo buffer, Oid relid)
+{
+ HeapTuple relTup;
+ Form_pg_class relForm;
+ char *nspname;
+ char *relname;
+
+ relTup = SearchSysCache1(RELOID,
+ ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(relTup))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+ relForm = (Form_pg_class) GETSTRUCT(relTup);
+
+ /* Qualify the name if not visible in search path */
+ if (RelationIsVisible(relid))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(relForm->relnamespace);
+
+ relname = quote_qualified_identifier(nspname, NameStr(relForm->relname));
+
+ switch (relForm->relkind)
+ {
+ case RELKIND_RELATION:
+ case RELKIND_PARTITIONED_TABLE:
+ appendStringInfo(buffer, _("table %s"),
+ relname);
+ break;
+ case RELKIND_INDEX:
+ case RELKIND_PARTITIONED_INDEX:
+ appendStringInfo(buffer, _("index %s"),
+ relname);
+ break;
+ case RELKIND_SEQUENCE:
+ appendStringInfo(buffer, _("sequence %s"),
+ relname);
+ break;
+ case RELKIND_TOASTVALUE:
+ appendStringInfo(buffer, _("toast table %s"),
+ relname);
+ break;
+ case RELKIND_VIEW:
+ appendStringInfo(buffer, _("view %s"),
+ relname);
+ break;
+ case RELKIND_MATVIEW:
+ appendStringInfo(buffer, _("materialized view %s"),
+ relname);
+ break;
+ case RELKIND_COMPOSITE_TYPE:
+ appendStringInfo(buffer, _("composite type %s"),
+ relname);
+ break;
+ case RELKIND_FOREIGN_TABLE:
+ appendStringInfo(buffer, _("foreign table %s"),
+ relname);
+ break;
+ default:
+ /* shouldn't get here */
+ appendStringInfo(buffer, _("relation %s"),
+ relname);
+ break;
+ }
+
+ ReleaseSysCache(relTup);
+}
+
+/*
+ * subroutine for getObjectDescription: describe an operator family
+ */
+static void
+getOpFamilyDescription(StringInfo buffer, Oid opfid)
+{
+ HeapTuple opfTup;
+ Form_pg_opfamily opfForm;
+ HeapTuple amTup;
+ Form_pg_am amForm;
+ char *nspname;
+
+ opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
+ if (!HeapTupleIsValid(opfTup))
+ elog(ERROR, "cache lookup failed for opfamily %u", opfid);
+ opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
+
+ amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
+ if (!HeapTupleIsValid(amTup))
+ elog(ERROR, "cache lookup failed for access method %u",
+ opfForm->opfmethod);
+ amForm = (Form_pg_am) GETSTRUCT(amTup);
+
+ /* Qualify the name if not visible in search path */
+ if (OpfamilyIsVisible(opfid))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(opfForm->opfnamespace);
+
+ appendStringInfo(buffer, _("operator family %s for access method %s"),
+ quote_qualified_identifier(nspname,
+ NameStr(opfForm->opfname)),
+ NameStr(amForm->amname));
+
+ ReleaseSysCache(amTup);
+ ReleaseSysCache(opfTup);
+}
+
+/*
+ * SQL-level callable version of getObjectDescription
+ */
+Datum
+pg_describe_object(PG_FUNCTION_ARGS)
+{
+ Oid classid = PG_GETARG_OID(0);
+ Oid objid = PG_GETARG_OID(1);
+ int32 objsubid = PG_GETARG_INT32(2);
+ char *description;
+ ObjectAddress address;
+
+ /* for "pinned" items in pg_depend, return null */
+ if (!OidIsValid(classid) && !OidIsValid(objid))
+ PG_RETURN_NULL();
+
+ address.classId = classid;
+ address.objectId = objid;
+ address.objectSubId = objsubid;
+
+ description = getObjectDescription(&address);
+ PG_RETURN_TEXT_P(cstring_to_text(description));
+}
+
+/*
+ * SQL-level callable function to obtain object type + identity
+ */
+Datum
+pg_identify_object(PG_FUNCTION_ARGS)
+{
+ Oid classid = PG_GETARG_OID(0);
+ Oid objid = PG_GETARG_OID(1);
+ int32 objsubid = PG_GETARG_INT32(2);
+ Oid schema_oid = InvalidOid;
+ const char *objname = NULL;
+ ObjectAddress address;
+ Datum values[4];
+ bool nulls[4];
+ TupleDesc tupdesc;
+ HeapTuple htup;
+
+ address.classId = classid;
+ address.objectId = objid;
+ address.objectSubId = objsubid;
+
+ /*
+ * Construct a tuple descriptor for the result row. This must match this
+ * function's pg_proc entry!
+ */
+ tupdesc = CreateTemplateTupleDesc(4);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "schema",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "name",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 4, "identity",
+ TEXTOID, -1, 0);
+
+ tupdesc = BlessTupleDesc(tupdesc);
+
+ if (is_objectclass_supported(address.classId))
+ {
+ HeapTuple objtup;
+ Relation catalog = table_open(address.classId, AccessShareLock);
+
+ objtup = get_catalog_object_by_oid(catalog,
+ get_object_attnum_oid(address.classId),
+ address.objectId);
+ if (objtup != NULL)
+ {
+ bool isnull;
+ AttrNumber nspAttnum;
+ AttrNumber nameAttnum;
+
+ nspAttnum = get_object_attnum_namespace(address.classId);
+ if (nspAttnum != InvalidAttrNumber)
+ {
+ schema_oid = heap_getattr(objtup, nspAttnum,
+ RelationGetDescr(catalog), &isnull);
+ if (isnull)
+ elog(ERROR, "invalid null namespace in object %u/%u/%d",
+ address.classId, address.objectId, address.objectSubId);
+ }
+
+ /*
+ * We only return the object name if it can be used (together with
+ * the schema name, if any) as a unique identifier.
+ */
+ if (get_object_namensp_unique(address.classId))
+ {
+ nameAttnum = get_object_attnum_name(address.classId);
+ if (nameAttnum != InvalidAttrNumber)
+ {
+ Datum nameDatum;
+
+ nameDatum = heap_getattr(objtup, nameAttnum,
+ RelationGetDescr(catalog), &isnull);
+ if (isnull)
+ elog(ERROR, "invalid null name in object %u/%u/%d",
+ address.classId, address.objectId, address.objectSubId);
+ objname = quote_identifier(NameStr(*(DatumGetName(nameDatum))));
+ }
+ }
+ }
+
+ table_close(catalog, AccessShareLock);
+ }
+
+ /* object type */
+ values[0] = CStringGetTextDatum(getObjectTypeDescription(&address));
+ nulls[0] = false;
+
+ /* schema name */
+ if (OidIsValid(schema_oid))
+ {
+ const char *schema = quote_identifier(get_namespace_name(schema_oid));
+
+ values[1] = CStringGetTextDatum(schema);
+ nulls[1] = false;
+ }
+ else
+ nulls[1] = true;
+
+ /* object name */
+ if (objname)
+ {
+ values[2] = CStringGetTextDatum(objname);
+ nulls[2] = false;
+ }
+ else
+ nulls[2] = true;
+
+ /* object identity */
+ values[3] = CStringGetTextDatum(getObjectIdentity(&address));
+ nulls[3] = false;
+
+ htup = heap_form_tuple(tupdesc, values, nulls);
+
+ PG_RETURN_DATUM(HeapTupleGetDatum(htup));
+}
+
+/*
+ * SQL-level callable function to obtain object type + identity
+ */
+Datum
+pg_identify_object_as_address(PG_FUNCTION_ARGS)
+{
+ Oid classid = PG_GETARG_OID(0);
+ Oid objid = PG_GETARG_OID(1);
+ int32 objsubid = PG_GETARG_INT32(2);
+ ObjectAddress address;
+ char *identity;
+ List *names;
+ List *args;
+ Datum values[3];
+ bool nulls[3];
+ TupleDesc tupdesc;
+ HeapTuple htup;
+
+ address.classId = classid;
+ address.objectId = objid;
+ address.objectSubId = objsubid;
+
+ /*
+ * Construct a tuple descriptor for the result row. This must match this
+ * function's pg_proc entry!
+ */
+ tupdesc = CreateTemplateTupleDesc(3);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "object_names",
+ TEXTARRAYOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "object_args",
+ TEXTARRAYOID, -1, 0);
+
+ tupdesc = BlessTupleDesc(tupdesc);
+
+ /* object type */
+ values[0] = CStringGetTextDatum(getObjectTypeDescription(&address));
+ nulls[0] = false;
+
+ /* object identity */
+ identity = getObjectIdentityParts(&address, &names, &args);
+ pfree(identity);
+
+ /* object_names */
+ if (names != NIL)
+ values[1] = PointerGetDatum(strlist_to_textarray(names));
+ else
+ values[1] = PointerGetDatum(construct_empty_array(TEXTOID));
+ nulls[1] = false;
+
+ /* object_args */
+ if (args)
+ values[2] = PointerGetDatum(strlist_to_textarray(args));
+ else
+ values[2] = PointerGetDatum(construct_empty_array(TEXTOID));
+ nulls[2] = false;
+
+ htup = heap_form_tuple(tupdesc, values, nulls);
+
+ PG_RETURN_DATUM(HeapTupleGetDatum(htup));
+}
+
+/*
+ * Return a palloc'ed string that describes the type of object that the
+ * passed address is for.
+ *
+ * Keep ObjectTypeMap in sync with this.
+ */
+char *
+getObjectTypeDescription(const ObjectAddress *object)
+{
+ StringInfoData buffer;
+
+ initStringInfo(&buffer);
+
+ switch (getObjectClass(object))
+ {
+ case OCLASS_CLASS:
+ getRelationTypeDescription(&buffer, object->objectId,
+ object->objectSubId);
+ break;
+
+ case OCLASS_PROC:
+ getProcedureTypeDescription(&buffer, object->objectId);
+ break;
+
+ case OCLASS_TYPE:
+ appendStringInfoString(&buffer, "type");
+ break;
+
+ case OCLASS_CAST:
+ appendStringInfoString(&buffer, "cast");
+ break;
+
+ case OCLASS_COLLATION:
+ appendStringInfoString(&buffer, "collation");
+ break;
+
+ case OCLASS_CONSTRAINT:
+ getConstraintTypeDescription(&buffer, object->objectId);
+ break;
+
+ case OCLASS_CONVERSION:
+ appendStringInfoString(&buffer, "conversion");
+ break;
+
+ case OCLASS_DEFAULT:
+ appendStringInfoString(&buffer, "default value");
+ break;
+
+ case OCLASS_LANGUAGE:
+ appendStringInfoString(&buffer, "language");
+ break;
+
+ case OCLASS_LARGEOBJECT:
+ appendStringInfoString(&buffer, "large object");
+ break;
+
+ case OCLASS_OPERATOR:
+ appendStringInfoString(&buffer, "operator");
+ break;
+
+ case OCLASS_OPCLASS:
+ appendStringInfoString(&buffer, "operator class");
+ break;
+
+ case OCLASS_OPFAMILY:
+ appendStringInfoString(&buffer, "operator family");
+ break;
+
+ case OCLASS_AM:
+ appendStringInfoString(&buffer, "access method");
+ break;
+
+ case OCLASS_AMOP:
+ appendStringInfoString(&buffer, "operator of access method");
+ break;
+
+ case OCLASS_AMPROC:
+ appendStringInfoString(&buffer, "function of access method");
+ break;
+
+ case OCLASS_REWRITE:
+ appendStringInfoString(&buffer, "rule");
+ break;
+
+ case OCLASS_TRIGGER:
+ appendStringInfoString(&buffer, "trigger");
+ break;
+
+ case OCLASS_SCHEMA:
+ appendStringInfoString(&buffer, "schema");
+ break;
+
+ case OCLASS_STATISTIC_EXT:
+ appendStringInfoString(&buffer, "statistics object");
+ break;
+
+ case OCLASS_TSPARSER:
+ appendStringInfoString(&buffer, "text search parser");
+ break;
+
+ case OCLASS_TSDICT:
+ appendStringInfoString(&buffer, "text search dictionary");
+ break;
+
+ case OCLASS_TSTEMPLATE:
+ appendStringInfoString(&buffer, "text search template");
+ break;
+
+ case OCLASS_TSCONFIG:
+ appendStringInfoString(&buffer, "text search configuration");
+ break;
+
+ case OCLASS_ROLE:
+ appendStringInfoString(&buffer, "role");
+ break;
+
+ case OCLASS_DATABASE:
+ appendStringInfoString(&buffer, "database");
+ break;
+
+ case OCLASS_TBLSPACE:
+ appendStringInfoString(&buffer, "tablespace");
+ break;
+
+ case OCLASS_FDW:
+ appendStringInfoString(&buffer, "foreign-data wrapper");
+ break;
+
+ case OCLASS_FOREIGN_SERVER:
+ appendStringInfoString(&buffer, "server");
+ break;
+
+ case OCLASS_USER_MAPPING:
+ appendStringInfoString(&buffer, "user mapping");
+ break;
+
+ case OCLASS_DEFACL:
+ appendStringInfoString(&buffer, "default acl");
+ break;
+
+ case OCLASS_EXTENSION:
+ appendStringInfoString(&buffer, "extension");
+ break;
+
+ case OCLASS_EVENT_TRIGGER:
+ appendStringInfoString(&buffer, "event trigger");
+ break;
+
+ case OCLASS_POLICY:
+ appendStringInfoString(&buffer, "policy");
+ break;
+
+ case OCLASS_PUBLICATION:
+ appendStringInfoString(&buffer, "publication");
+ break;
+
+ case OCLASS_PUBLICATION_REL:
+ appendStringInfoString(&buffer, "publication relation");
+ break;
+
+ case OCLASS_SUBSCRIPTION:
+ appendStringInfoString(&buffer, "subscription");
+ break;
+
+ case OCLASS_TRANSFORM:
+ appendStringInfoString(&buffer, "transform");
+ break;
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
+ }
+
+ return buffer.data;
+}
+
+/*
+ * subroutine for getObjectTypeDescription: describe a relation type
+ */
+static void
+getRelationTypeDescription(StringInfo buffer, Oid relid, int32 objectSubId)
+{
+ HeapTuple relTup;
+ Form_pg_class relForm;
+
+ relTup = SearchSysCache1(RELOID,
+ ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(relTup))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+ relForm = (Form_pg_class) GETSTRUCT(relTup);
+
+ switch (relForm->relkind)
+ {
+ case RELKIND_RELATION:
+ case RELKIND_PARTITIONED_TABLE:
+ appendStringInfoString(buffer, "table");
+ break;
+ case RELKIND_INDEX:
+ case RELKIND_PARTITIONED_INDEX:
+ appendStringInfoString(buffer, "index");
+ break;
+ case RELKIND_SEQUENCE:
+ appendStringInfoString(buffer, "sequence");
+ break;
+ case RELKIND_TOASTVALUE:
+ appendStringInfoString(buffer, "toast table");
+ break;
+ case RELKIND_VIEW:
+ appendStringInfoString(buffer, "view");
+ break;
+ case RELKIND_MATVIEW:
+ appendStringInfoString(buffer, "materialized view");
+ break;
+ case RELKIND_COMPOSITE_TYPE:
+ appendStringInfoString(buffer, "composite type");
+ break;
+ case RELKIND_FOREIGN_TABLE:
+ appendStringInfoString(buffer, "foreign table");
+ break;
+ default:
+ /* shouldn't get here */
+ appendStringInfoString(buffer, "relation");
+ break;
+ }
+
+ if (objectSubId != 0)
+ appendStringInfoString(buffer, " column");
+
+ ReleaseSysCache(relTup);
+}
+
+/*
+ * subroutine for getObjectTypeDescription: describe a constraint type
+ */
+static void
+getConstraintTypeDescription(StringInfo buffer, Oid constroid)
+{
+ Relation constrRel;
+ HeapTuple constrTup;
+ Form_pg_constraint constrForm;
+
+ constrRel = table_open(ConstraintRelationId, AccessShareLock);
+ constrTup = get_catalog_object_by_oid(constrRel, Anum_pg_constraint_oid,
+ constroid);
+ if (!HeapTupleIsValid(constrTup))
+ elog(ERROR, "cache lookup failed for constraint %u", constroid);
+
+ constrForm = (Form_pg_constraint) GETSTRUCT(constrTup);
+
+ if (OidIsValid(constrForm->conrelid))
+ appendStringInfoString(buffer, "table constraint");
+ else if (OidIsValid(constrForm->contypid))
+ appendStringInfoString(buffer, "domain constraint");
+ else
+ elog(ERROR, "invalid constraint %u", constrForm->oid);
+
+ table_close(constrRel, AccessShareLock);
+}
+
+/*
+ * subroutine for getObjectTypeDescription: describe a procedure type
+ */
+static void
+getProcedureTypeDescription(StringInfo buffer, Oid procid)
+{
+ HeapTuple procTup;
+ Form_pg_proc procForm;
+
+ procTup = SearchSysCache1(PROCOID,
+ ObjectIdGetDatum(procid));
+ if (!HeapTupleIsValid(procTup))
+ elog(ERROR, "cache lookup failed for procedure %u", procid);
+ procForm = (Form_pg_proc) GETSTRUCT(procTup);
+
+ if (procForm->prokind == PROKIND_AGGREGATE)
+ appendStringInfoString(buffer, "aggregate");
+ else if (procForm->prokind == PROKIND_PROCEDURE)
+ appendStringInfoString(buffer, "procedure");
+ else /* function or window function */
+ appendStringInfoString(buffer, "function");
+
+ ReleaseSysCache(procTup);
+}
+
+/*
+ * Obtain a given object's identity, as a palloc'ed string.
+ *
+ * This is for machine consumption, so it's not translated. All elements are
+ * schema-qualified when appropriate.
+ */
+char *
+getObjectIdentity(const ObjectAddress *object)
+{
+ return getObjectIdentityParts(object, NULL, NULL);
+}
+
+/*
+ * As above, but more detailed.
+ *
+ * There are two sets of return values: the identity itself as a palloc'd
+ * string is returned. objname and objargs, if not NULL, are output parameters
+ * that receive lists of C-strings that are useful to give back to
+ * get_object_address() to reconstruct the ObjectAddress.
+ */
+char *
+getObjectIdentityParts(const ObjectAddress *object,
+ List **objname, List **objargs)
+{
+ StringInfoData buffer;
+
+ initStringInfo(&buffer);
+
+ /*
+ * Make sure that both objname and objargs were passed, or none was; and
+ * initialize them to empty lists. For objname this is useless because it
+ * will be initialized in all cases inside the switch; but we do it anyway
+ * so that we can test below that no branch leaves it unset.
+ */
+ Assert(PointerIsValid(objname) == PointerIsValid(objargs));
+ if (objname)
+ {
+ *objname = NIL;
+ *objargs = NIL;
+ }
+
+ switch (getObjectClass(object))
+ {
+ case OCLASS_CLASS:
+ getRelationIdentity(&buffer, object->objectId, objname);
+ if (object->objectSubId != 0)
+ {
+ char *attr;
+
+ attr = get_attname(object->objectId, object->objectSubId,
+ false);
+ appendStringInfo(&buffer, ".%s", quote_identifier(attr));
+ if (objname)
+ *objname = lappend(*objname, attr);
+ }
+ break;
+
+ case OCLASS_PROC:
+ appendStringInfoString(&buffer,
+ format_procedure_qualified(object->objectId));
+ if (objname)
+ format_procedure_parts(object->objectId, objname, objargs);
+ break;
+
+ case OCLASS_TYPE:
+ {
+ char *typeout;
+
+ typeout = format_type_be_qualified(object->objectId);
+ appendStringInfoString(&buffer, typeout);
+ if (objname)
+ *objname = list_make1(typeout);
+ }
+ break;
+
+ case OCLASS_CAST:
+ {
+ Relation castRel;
+ HeapTuple tup;
+ Form_pg_cast castForm;
+
+ castRel = table_open(CastRelationId, AccessShareLock);
+
+ tup = get_catalog_object_by_oid(castRel, Anum_pg_cast_oid,
+ object->objectId);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for cast %u",
+ object->objectId);
+
+ castForm = (Form_pg_cast) GETSTRUCT(tup);
+
+ appendStringInfo(&buffer, "(%s AS %s)",
+ format_type_be_qualified(castForm->castsource),
+ format_type_be_qualified(castForm->casttarget));
+
+ if (objname)
+ {
+ *objname = list_make1(format_type_be_qualified(castForm->castsource));
+ *objargs = list_make1(format_type_be_qualified(castForm->casttarget));
+ }
+
+ table_close(castRel, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_COLLATION:
+ {
+ HeapTuple collTup;
+ Form_pg_collation coll;
+ char *schema;
+
+ collTup = SearchSysCache1(COLLOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(collTup))
+ elog(ERROR, "cache lookup failed for collation %u",
+ object->objectId);
+ coll = (Form_pg_collation) GETSTRUCT(collTup);
+ schema = get_namespace_name_or_temp(coll->collnamespace);
+ appendStringInfoString(&buffer,
+ quote_qualified_identifier(schema,
+ NameStr(coll->collname)));
+ if (objname)
+ *objname = list_make2(schema,
+ pstrdup(NameStr(coll->collname)));
+ ReleaseSysCache(collTup);
+ break;
+ }
+
+ case OCLASS_CONSTRAINT:
+ {
+ HeapTuple conTup;
+ Form_pg_constraint con;
+
+ conTup = SearchSysCache1(CONSTROID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(conTup))
+ elog(ERROR, "cache lookup failed for constraint %u",
+ object->objectId);
+ con = (Form_pg_constraint) GETSTRUCT(conTup);
+
+ if (OidIsValid(con->conrelid))
+ {
+ appendStringInfo(&buffer, "%s on ",
+ quote_identifier(NameStr(con->conname)));
+ getRelationIdentity(&buffer, con->conrelid, objname);
+ if (objname)
+ *objname = lappend(*objname, pstrdup(NameStr(con->conname)));
+ }
+ else
+ {
+ ObjectAddress domain;
+
+ Assert(OidIsValid(con->contypid));
+ domain.classId = TypeRelationId;
+ domain.objectId = con->contypid;
+ domain.objectSubId = 0;
+
+ appendStringInfo(&buffer, "%s on %s",
+ quote_identifier(NameStr(con->conname)),
+ getObjectIdentityParts(&domain, objname, objargs));
+
+ if (objname)
+ *objargs = lappend(*objargs, pstrdup(NameStr(con->conname)));
+ }
+
+ ReleaseSysCache(conTup);
+ break;
+ }
+
+ case OCLASS_CONVERSION:
+ {
+ HeapTuple conTup;
+ Form_pg_conversion conForm;
+ char *schema;
+
+ conTup = SearchSysCache1(CONVOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(conTup))
+ elog(ERROR, "cache lookup failed for conversion %u",
+ object->objectId);
+ conForm = (Form_pg_conversion) GETSTRUCT(conTup);
+ schema = get_namespace_name_or_temp(conForm->connamespace);
+ appendStringInfoString(&buffer,
+ quote_qualified_identifier(schema,
+ NameStr(conForm->conname)));
+ if (objname)
+ *objname = list_make2(schema,
+ pstrdup(NameStr(conForm->conname)));
+ ReleaseSysCache(conTup);
+ break;
+ }
+
+ case OCLASS_DEFAULT:
+ {
+ Relation attrdefDesc;
+ ScanKeyData skey[1];
+ SysScanDesc adscan;
+
+ HeapTuple tup;
+ Form_pg_attrdef attrdef;
+ ObjectAddress colobject;
+
+ attrdefDesc = table_open(AttrDefaultRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_attrdef_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndexId,
+ true, NULL, 1, skey);
+
+ tup = systable_getnext(adscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for attrdef %u",
+ object->objectId);
+
+ attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
+
+ colobject.classId = RelationRelationId;
+ colobject.objectId = attrdef->adrelid;
+ colobject.objectSubId = attrdef->adnum;
+
+ appendStringInfo(&buffer, "for %s",
+ getObjectIdentityParts(&colobject,
+ objname, objargs));
+
+ systable_endscan(adscan);
+ table_close(attrdefDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_LANGUAGE:
+ {
+ HeapTuple langTup;
+ Form_pg_language langForm;
+
+ langTup = SearchSysCache1(LANGOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(langTup))
+ elog(ERROR, "cache lookup failed for language %u",
+ object->objectId);
+ langForm = (Form_pg_language) GETSTRUCT(langTup);
+ appendStringInfoString(&buffer,
+ quote_identifier(NameStr(langForm->lanname)));
+ if (objname)
+ *objname = list_make1(pstrdup(NameStr(langForm->lanname)));
+ ReleaseSysCache(langTup);
+ break;
+ }
+ case OCLASS_LARGEOBJECT:
+ appendStringInfo(&buffer, "%u",
+ object->objectId);
+ if (objname)
+ *objname = list_make1(psprintf("%u", object->objectId));
+ break;
+
+ case OCLASS_OPERATOR:
+ appendStringInfoString(&buffer,
+ format_operator_qualified(object->objectId));
+ if (objname)
+ format_operator_parts(object->objectId, objname, objargs);
+ break;
+
+ case OCLASS_OPCLASS:
+ {
+ HeapTuple opcTup;
+ Form_pg_opclass opcForm;
+ HeapTuple amTup;
+ Form_pg_am amForm;
+ char *schema;
+
+ opcTup = SearchSysCache1(CLAOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(opcTup))
+ elog(ERROR, "cache lookup failed for opclass %u",
+ object->objectId);
+ opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
+ schema = get_namespace_name_or_temp(opcForm->opcnamespace);
+
+ amTup = SearchSysCache1(AMOID,
+ ObjectIdGetDatum(opcForm->opcmethod));
+ if (!HeapTupleIsValid(amTup))
+ elog(ERROR, "cache lookup failed for access method %u",
+ opcForm->opcmethod);
+ amForm = (Form_pg_am) GETSTRUCT(amTup);
+
+ appendStringInfo(&buffer, "%s USING %s",
+ quote_qualified_identifier(schema,
+ NameStr(opcForm->opcname)),
+ quote_identifier(NameStr(amForm->amname)));
+ if (objname)
+ *objname = list_make3(pstrdup(NameStr(amForm->amname)),
+ schema,
+ pstrdup(NameStr(opcForm->opcname)));
+
+ ReleaseSysCache(amTup);
+ ReleaseSysCache(opcTup);
+ break;
+ }
+
+ case OCLASS_OPFAMILY:
+ getOpFamilyIdentity(&buffer, object->objectId, objname);
+ break;
+
+ case OCLASS_AM:
+ {
+ char *amname;
+
+ amname = get_am_name(object->objectId);
+ if (!amname)
+ elog(ERROR, "cache lookup failed for access method %u",
+ object->objectId);
+ appendStringInfoString(&buffer, quote_identifier(amname));
+ if (objname)
+ *objname = list_make1(amname);
+ }
+ break;
+
+ case OCLASS_AMOP:
+ {
+ Relation amopDesc;
+ HeapTuple tup;
+ ScanKeyData skey[1];
+ SysScanDesc amscan;
+ Form_pg_amop amopForm;
+ StringInfoData opfam;
+ char *ltype;
+ char *rtype;
+
+ amopDesc = table_open(AccessMethodOperatorRelationId,
+ AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_amop_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ amscan = systable_beginscan(amopDesc, AccessMethodOperatorOidIndexId, true,
+ NULL, 1, skey);
+
+ tup = systable_getnext(amscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for amop entry %u",
+ object->objectId);
+
+ amopForm = (Form_pg_amop) GETSTRUCT(tup);
+
+ initStringInfo(&opfam);
+ getOpFamilyIdentity(&opfam, amopForm->amopfamily, objname);
+
+ ltype = format_type_be_qualified(amopForm->amoplefttype);
+ rtype = format_type_be_qualified(amopForm->amoprighttype);
+
+ if (objname)
+ {
+ *objname = lappend(*objname,
+ psprintf("%d", amopForm->amopstrategy));
+ *objargs = list_make2(ltype, rtype);
+ }
+
+ appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
+ amopForm->amopstrategy,
+ ltype, rtype, opfam.data);
+
+ pfree(opfam.data);
+
+ systable_endscan(amscan);
+ table_close(amopDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_AMPROC:
+ {
+ Relation amprocDesc;
+ ScanKeyData skey[1];
+ SysScanDesc amscan;
+ HeapTuple tup;
+ Form_pg_amproc amprocForm;
+ StringInfoData opfam;
+ char *ltype;
+ char *rtype;
+
+ amprocDesc = table_open(AccessMethodProcedureRelationId,
+ AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_amproc_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ amscan = systable_beginscan(amprocDesc, AccessMethodProcedureOidIndexId, true,
+ NULL, 1, skey);
+
+ tup = systable_getnext(amscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for amproc entry %u",
+ object->objectId);
+
+ amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
+
+ initStringInfo(&opfam);
+ getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, objname);
+
+ ltype = format_type_be_qualified(amprocForm->amproclefttype);
+ rtype = format_type_be_qualified(amprocForm->amprocrighttype);
+
+ if (objname)
+ {
+ *objname = lappend(*objname,
+ psprintf("%d", amprocForm->amprocnum));
+ *objargs = list_make2(ltype, rtype);
+ }
+
+ appendStringInfo(&buffer, "function %d (%s, %s) of %s",
+ amprocForm->amprocnum,
+ ltype, rtype, opfam.data);
+
+ pfree(opfam.data);
+
+ systable_endscan(amscan);
+ table_close(amprocDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_REWRITE:
+ {
+ Relation ruleDesc;
+ HeapTuple tup;
+ Form_pg_rewrite rule;
+
+ ruleDesc = table_open(RewriteRelationId, AccessShareLock);
+
+ tup = get_catalog_object_by_oid(ruleDesc, Anum_pg_rewrite_oid,
+ object->objectId);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for rule %u",
+ object->objectId);
+
+ rule = (Form_pg_rewrite) GETSTRUCT(tup);
+
+ appendStringInfo(&buffer, "%s on ",
+ quote_identifier(NameStr(rule->rulename)));
+ getRelationIdentity(&buffer, rule->ev_class, objname);
+ if (objname)
+ *objname = lappend(*objname, pstrdup(NameStr(rule->rulename)));
+
+ table_close(ruleDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_TRIGGER:
+ {
+ Relation trigDesc;
+ HeapTuple tup;
+ Form_pg_trigger trig;
+
+ trigDesc = table_open(TriggerRelationId, AccessShareLock);
+
+ tup = get_catalog_object_by_oid(trigDesc, Anum_pg_trigger_oid,
+ object->objectId);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for trigger %u",
+ object->objectId);
+
+ trig = (Form_pg_trigger) GETSTRUCT(tup);
+
+ appendStringInfo(&buffer, "%s on ",
+ quote_identifier(NameStr(trig->tgname)));
+ getRelationIdentity(&buffer, trig->tgrelid, objname);
+ if (objname)
+ *objname = lappend(*objname, pstrdup(NameStr(trig->tgname)));
+
+ table_close(trigDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_SCHEMA:
+ {
+ char *nspname;
+
+ nspname = get_namespace_name_or_temp(object->objectId);
+ if (!nspname)
+ elog(ERROR, "cache lookup failed for namespace %u",
+ object->objectId);
+ appendStringInfoString(&buffer,
+ quote_identifier(nspname));
+ if (objname)
+ *objname = list_make1(nspname);
+ break;
+ }
+
+ case OCLASS_STATISTIC_EXT:
+ {
+ HeapTuple tup;
+ Form_pg_statistic_ext formStatistic;
+ char *schema;
+
+ tup = SearchSysCache1(STATEXTOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for statistics object %u",
+ object->objectId);
+ formStatistic = (Form_pg_statistic_ext) GETSTRUCT(tup);
+ schema = get_namespace_name_or_temp(formStatistic->stxnamespace);
+ appendStringInfoString(&buffer,
+ quote_qualified_identifier(schema,
+ NameStr(formStatistic->stxname)));
+ if (objname)
+ *objname = list_make2(schema,
+ pstrdup(NameStr(formStatistic->stxname)));
+ ReleaseSysCache(tup);
+ }
+ break;
+
+ case OCLASS_TSPARSER:
+ {
+ HeapTuple tup;
+ Form_pg_ts_parser formParser;
+ char *schema;
+
+ tup = SearchSysCache1(TSPARSEROID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search parser %u",
+ object->objectId);
+ formParser = (Form_pg_ts_parser) GETSTRUCT(tup);
+ schema = get_namespace_name_or_temp(formParser->prsnamespace);
+ appendStringInfoString(&buffer,
+ quote_qualified_identifier(schema,
+ NameStr(formParser->prsname)));
+ if (objname)
+ *objname = list_make2(schema,
+ pstrdup(NameStr(formParser->prsname)));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_TSDICT:
+ {
+ HeapTuple tup;
+ Form_pg_ts_dict formDict;
+ char *schema;
+
+ tup = SearchSysCache1(TSDICTOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search dictionary %u",
+ object->objectId);
+ formDict = (Form_pg_ts_dict) GETSTRUCT(tup);
+ schema = get_namespace_name_or_temp(formDict->dictnamespace);
+ appendStringInfoString(&buffer,
+ quote_qualified_identifier(schema,
+ NameStr(formDict->dictname)));
+ if (objname)
+ *objname = list_make2(schema,
+ pstrdup(NameStr(formDict->dictname)));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_TSTEMPLATE:
+ {
+ HeapTuple tup;
+ Form_pg_ts_template formTmpl;
+ char *schema;
+
+ tup = SearchSysCache1(TSTEMPLATEOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search template %u",
+ object->objectId);
+ formTmpl = (Form_pg_ts_template) GETSTRUCT(tup);
+ schema = get_namespace_name_or_temp(formTmpl->tmplnamespace);
+ appendStringInfoString(&buffer,
+ quote_qualified_identifier(schema,
+ NameStr(formTmpl->tmplname)));
+ if (objname)
+ *objname = list_make2(schema,
+ pstrdup(NameStr(formTmpl->tmplname)));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_TSCONFIG:
+ {
+ HeapTuple tup;
+ Form_pg_ts_config formCfg;
+ char *schema;
+
+ tup = SearchSysCache1(TSCONFIGOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for text search configuration %u",
+ object->objectId);
+ formCfg = (Form_pg_ts_config) GETSTRUCT(tup);
+ schema = get_namespace_name_or_temp(formCfg->cfgnamespace);
+ appendStringInfoString(&buffer,
+ quote_qualified_identifier(schema,
+ NameStr(formCfg->cfgname)));
+ if (objname)
+ *objname = list_make2(schema,
+ pstrdup(NameStr(formCfg->cfgname)));
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_ROLE:
+ {
+ char *username;
+
+ username = GetUserNameFromId(object->objectId, false);
+ if (objname)
+ *objname = list_make1(username);
+ appendStringInfoString(&buffer,
+ quote_identifier(username));
+ break;
+ }
+
+ case OCLASS_DATABASE:
+ {
+ char *datname;
+
+ datname = get_database_name(object->objectId);
+ if (!datname)
+ elog(ERROR, "cache lookup failed for database %u",
+ object->objectId);
+ if (objname)
+ *objname = list_make1(datname);
+ appendStringInfoString(&buffer,
+ quote_identifier(datname));
+ break;
+ }
+
+ case OCLASS_TBLSPACE:
+ {
+ char *tblspace;
+
+ tblspace = get_tablespace_name(object->objectId);
+ if (!tblspace)
+ elog(ERROR, "cache lookup failed for tablespace %u",
+ object->objectId);
+ if (objname)
+ *objname = list_make1(tblspace);
+ appendStringInfoString(&buffer,
+ quote_identifier(tblspace));
+ break;
+ }
+
+ case OCLASS_FDW:
+ {
+ ForeignDataWrapper *fdw;
+
+ fdw = GetForeignDataWrapper(object->objectId);
+ appendStringInfoString(&buffer, quote_identifier(fdw->fdwname));
+ if (objname)
+ *objname = list_make1(pstrdup(fdw->fdwname));
+ break;
+ }
+
+ case OCLASS_FOREIGN_SERVER:
+ {
+ ForeignServer *srv;
+
+ srv = GetForeignServer(object->objectId);
+ appendStringInfoString(&buffer,
+ quote_identifier(srv->servername));
+ if (objname)
+ *objname = list_make1(pstrdup(srv->servername));
+ break;
+ }
+
+ case OCLASS_USER_MAPPING:
+ {
+ HeapTuple tup;
+ Oid useid;
+ Form_pg_user_mapping umform;
+ ForeignServer *srv;
+ const char *usename;
+
+ tup = SearchSysCache1(USERMAPPINGOID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for user mapping %u",
+ object->objectId);
+ umform = (Form_pg_user_mapping) GETSTRUCT(tup);
+ useid = umform->umuser;
+ srv = GetForeignServer(umform->umserver);
+
+ ReleaseSysCache(tup);
+
+ if (OidIsValid(useid))
+ usename = GetUserNameFromId(useid, false);
+ else
+ usename = "public";
+
+ if (objname)
+ {
+ *objname = list_make1(pstrdup(usename));
+ *objargs = list_make1(pstrdup(srv->servername));
+ }
+
+ appendStringInfo(&buffer, "%s on server %s",
+ quote_identifier(usename),
+ srv->servername);
+ break;
+ }
+
+ case OCLASS_DEFACL:
+ {
+ Relation defaclrel;
+ ScanKeyData skey[1];
+ SysScanDesc rcscan;
+ HeapTuple tup;
+ Form_pg_default_acl defacl;
+ char *schema;
+ char *username;
+
+ defaclrel = table_open(DefaultAclRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_default_acl_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ rcscan = systable_beginscan(defaclrel, DefaultAclOidIndexId,
+ true, NULL, 1, skey);
+
+ tup = systable_getnext(rcscan);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for default ACL %u",
+ object->objectId);
+
+ defacl = (Form_pg_default_acl) GETSTRUCT(tup);
+
+ username = GetUserNameFromId(defacl->defaclrole, false);
+ appendStringInfo(&buffer,
+ "for role %s",
+ quote_identifier(username));
+
+ if (OidIsValid(defacl->defaclnamespace))
+ {
+ schema = get_namespace_name_or_temp(defacl->defaclnamespace);
+ appendStringInfo(&buffer,
+ " in schema %s",
+ quote_identifier(schema));
+ }
+ else
+ schema = NULL;
+
+ switch (defacl->defaclobjtype)
+ {
+ case DEFACLOBJ_RELATION:
+ appendStringInfoString(&buffer,
+ " on tables");
+ break;
+ case DEFACLOBJ_SEQUENCE:
+ appendStringInfoString(&buffer,
+ " on sequences");
+ break;
+ case DEFACLOBJ_FUNCTION:
+ appendStringInfoString(&buffer,
+ " on functions");
+ break;
+ case DEFACLOBJ_TYPE:
+ appendStringInfoString(&buffer,
+ " on types");
+ break;
+ case DEFACLOBJ_NAMESPACE:
+ appendStringInfoString(&buffer,
+ " on schemas");
+ break;
+ }
+
+ if (objname)
+ {
+ *objname = list_make1(username);
+ if (schema)
+ *objname = lappend(*objname, schema);
+ *objargs = list_make1(psprintf("%c", defacl->defaclobjtype));
+ }
+
+ systable_endscan(rcscan);
+ table_close(defaclrel, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_EXTENSION:
+ {
+ char *extname;
+
+ extname = get_extension_name(object->objectId);
+ if (!extname)
+ elog(ERROR, "cache lookup failed for extension %u",
+ object->objectId);
+ appendStringInfoString(&buffer, quote_identifier(extname));
+ if (objname)
+ *objname = list_make1(extname);
+ break;
+ }
+
+ case OCLASS_EVENT_TRIGGER:
+ {
+ HeapTuple tup;
+ Form_pg_event_trigger trigForm;
+ char *evtname;
+
+ tup = SearchSysCache1(EVENTTRIGGEROID,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for event trigger %u",
+ object->objectId);
+ trigForm = (Form_pg_event_trigger) GETSTRUCT(tup);
+ evtname = pstrdup(NameStr(trigForm->evtname));
+ appendStringInfoString(&buffer, quote_identifier(evtname));
+ if (objname)
+ *objname = list_make1(evtname);
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_POLICY:
+ {
+ Relation polDesc;
+ HeapTuple tup;
+ Form_pg_policy policy;
+
+ polDesc = table_open(PolicyRelationId, AccessShareLock);
+
+ tup = get_catalog_object_by_oid(polDesc, Anum_pg_policy_oid,
+ object->objectId);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for policy %u",
+ object->objectId);
+
+ policy = (Form_pg_policy) GETSTRUCT(tup);
+
+ appendStringInfo(&buffer, "%s on ",
+ quote_identifier(NameStr(policy->polname)));
+ getRelationIdentity(&buffer, policy->polrelid, objname);
+ if (objname)
+ *objname = lappend(*objname, pstrdup(NameStr(policy->polname)));
+
+ table_close(polDesc, AccessShareLock);
+ break;
+ }
+
+ case OCLASS_PUBLICATION:
+ {
+ char *pubname;
+
+ pubname = get_publication_name(object->objectId, false);
+ appendStringInfoString(&buffer,
+ quote_identifier(pubname));
+ if (objname)
+ *objname = list_make1(pubname);
+ break;
+ }
+
+ case OCLASS_PUBLICATION_REL:
+ {
+ HeapTuple tup;
+ char *pubname;
+ Form_pg_publication_rel prform;
+
+ tup = SearchSysCache1(PUBLICATIONREL,
+ ObjectIdGetDatum(object->objectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for publication table %u",
+ object->objectId);
+
+ prform = (Form_pg_publication_rel) GETSTRUCT(tup);
+ pubname = get_publication_name(prform->prpubid, false);
+
+ getRelationIdentity(&buffer, prform->prrelid, objname);
+ appendStringInfo(&buffer, " in publication %s", pubname);
+
+ if (objargs)
+ *objargs = list_make1(pubname);
+
+ ReleaseSysCache(tup);
+ break;
+ }
+
+ case OCLASS_SUBSCRIPTION:
+ {
+ char *subname;
+
+ subname = get_subscription_name(object->objectId, false);
+ appendStringInfoString(&buffer,
+ quote_identifier(subname));
+ if (objname)
+ *objname = list_make1(subname);
+ break;
+ }
+
+ case OCLASS_TRANSFORM:
+ {
+ Relation transformDesc;
+ HeapTuple tup;
+ Form_pg_transform transform;
+ char *transformLang;
+ char *transformType;
+
+ transformDesc = table_open(TransformRelationId, AccessShareLock);
+
+ tup = get_catalog_object_by_oid(transformDesc,
+ Anum_pg_transform_oid,
+ object->objectId);
+
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "could not find tuple for transform %u",
+ object->objectId);
+
+ transform = (Form_pg_transform) GETSTRUCT(tup);
+
+ transformType = format_type_be_qualified(transform->trftype);
+ transformLang = get_language_name(transform->trflang, false);
+
+ appendStringInfo(&buffer, "for %s on language %s",
+ transformType,
+ transformLang);
+ if (objname)
+ {
+ *objname = list_make1(transformType);
+ *objargs = list_make1(pstrdup(transformLang));
+ }
+
+ table_close(transformDesc, AccessShareLock);
+ }
+ break;
+
+ /*
+ * There's intentionally no default: case here; we want the
+ * compiler to warn if a new OCLASS hasn't been handled above.
+ */
+ }
+
+ /*
+ * If a get_object_address representation was requested, make sure we are
+ * providing one. We don't check objargs, because many of the cases above
+ * leave it as NIL.
+ */
+ if (objname && *objname == NIL)
+ elog(ERROR, "requested object address for unsupported object class %d: text result \"%s\"",
+ (int) getObjectClass(object), buffer.data);
+
+ return buffer.data;
+}
+
+static void
+getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object)
+{
+ HeapTuple opfTup;
+ Form_pg_opfamily opfForm;
+ HeapTuple amTup;
+ Form_pg_am amForm;
+ char *schema;
+
+ opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
+ if (!HeapTupleIsValid(opfTup))
+ elog(ERROR, "cache lookup failed for opfamily %u", opfid);
+ opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
+
+ amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
+ if (!HeapTupleIsValid(amTup))
+ elog(ERROR, "cache lookup failed for access method %u",
+ opfForm->opfmethod);
+ amForm = (Form_pg_am) GETSTRUCT(amTup);
+
+ schema = get_namespace_name_or_temp(opfForm->opfnamespace);
+ appendStringInfo(buffer, "%s USING %s",
+ quote_qualified_identifier(schema,
+ NameStr(opfForm->opfname)),
+ NameStr(amForm->amname));
+
+ if (object)
+ *object = list_make3(pstrdup(NameStr(amForm->amname)),
+ pstrdup(schema),
+ pstrdup(NameStr(opfForm->opfname)));
+
+ ReleaseSysCache(amTup);
+ ReleaseSysCache(opfTup);
+}
+
+/*
+ * Append the relation identity (quoted qualified name) to the given
+ * StringInfo.
+ */
+static void
+getRelationIdentity(StringInfo buffer, Oid relid, List **object)
+{
+ HeapTuple relTup;
+ Form_pg_class relForm;
+ char *schema;
+
+ relTup = SearchSysCache1(RELOID,
+ ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(relTup))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+ relForm = (Form_pg_class) GETSTRUCT(relTup);
+
+ schema = get_namespace_name_or_temp(relForm->relnamespace);
+ appendStringInfoString(buffer,
+ quote_qualified_identifier(schema,
+ NameStr(relForm->relname)));
+ if (object)
+ *object = list_make2(schema, pstrdup(NameStr(relForm->relname)));
+
+ ReleaseSysCache(relTup);
+}
+
+/*
+ * Auxiliary function to build a TEXT array out of a list of C-strings.
+ */
+ArrayType *
+strlist_to_textarray(List *list)
+{
+ ArrayType *arr;
+ Datum *datums;
+ bool *nulls;
+ int j = 0;
+ ListCell *cell;
+ MemoryContext memcxt;
+ MemoryContext oldcxt;
+ int lb[1];
+
+ /* Work in a temp context; easier than individually pfree'ing the Datums */
+ memcxt = AllocSetContextCreate(CurrentMemoryContext,
+ "strlist to array",
+ ALLOCSET_DEFAULT_SIZES);
+ oldcxt = MemoryContextSwitchTo(memcxt);
+
+ datums = (Datum *) palloc(sizeof(Datum) * list_length(list));
+ nulls = palloc(sizeof(bool) * list_length(list));
+
+ foreach(cell, list)
+ {
+ char *name = lfirst(cell);
+
+ if (name)
+ {
+ nulls[j] = false;
+ datums[j++] = CStringGetTextDatum(name);
+ }
+ else
+ nulls[j] = true;
+ }
+
+ MemoryContextSwitchTo(oldcxt);
+
+ lb[0] = 1;
+ arr = construct_md_array(datums, nulls, 1, &j,
+ lb, TEXTOID, -1, false, TYPALIGN_INT);
+
+ MemoryContextDelete(memcxt);
+
+ return arr;
+}
+
+/*
+ * get_relkind_objtype
+ *
+ * Return the object type for the relkind given by the caller.
+ *
+ * If an unexpected relkind is passed, we say OBJECT_TABLE rather than
+ * failing. That's because this is mostly used for generating error messages
+ * for failed ACL checks on relations, and we'd rather produce a generic
+ * message saying "table" than fail entirely.
+ */
+ObjectType
+get_relkind_objtype(char relkind)
+{
+ switch (relkind)
+ {
+ case RELKIND_RELATION:
+ case RELKIND_PARTITIONED_TABLE:
+ return OBJECT_TABLE;
+ case RELKIND_INDEX:
+ case RELKIND_PARTITIONED_INDEX:
+ return OBJECT_INDEX;
+ case RELKIND_SEQUENCE:
+ return OBJECT_SEQUENCE;
+ case RELKIND_VIEW:
+ return OBJECT_VIEW;
+ case RELKIND_MATVIEW:
+ return OBJECT_MATVIEW;
+ case RELKIND_FOREIGN_TABLE:
+ return OBJECT_FOREIGN_TABLE;
+ case RELKIND_TOASTVALUE:
+ return OBJECT_TABLE;
+ default:
+ /* Per above, don't raise an error */
+ return OBJECT_TABLE;
+ }
+}
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
new file mode 100644
index 0000000..4dfac39
--- /dev/null
+++ b/src/backend/catalog/partition.c
@@ -0,0 +1,368 @@
+/*-------------------------------------------------------------------------
+ *
+ * partition.c
+ * Partitioning related data structures and functions.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/partition.c
+ *
+ *-------------------------------------------------------------------------
+*/
+#include "postgres.h"
+
+#include "access/attmap.h"
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/table.h"
+#include "catalog/indexing.h"
+#include "catalog/partition.h"
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_partitioned_table.h"
+#include "nodes/makefuncs.h"
+#include "optimizer/optimizer.h"
+#include "partitioning/partbounds.h"
+#include "rewrite/rewriteManip.h"
+#include "utils/fmgroids.h"
+#include "utils/partcache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+static Oid get_partition_parent_worker(Relation inhRel, Oid relid);
+static void get_partition_ancestors_worker(Relation inhRel, Oid relid,
+ List **ancestors);
+
+/*
+ * get_partition_parent
+ * Obtain direct parent of given relation
+ *
+ * Returns inheritance parent of a partition by scanning pg_inherits
+ *
+ * Note: Because this function assumes that the relation whose OID is passed
+ * as an argument will have precisely one parent, it should only be called
+ * when it is known that the relation is a partition.
+ */
+Oid
+get_partition_parent(Oid relid)
+{
+ Relation catalogRelation;
+ Oid result;
+
+ catalogRelation = table_open(InheritsRelationId, AccessShareLock);
+
+ result = get_partition_parent_worker(catalogRelation, relid);
+
+ if (!OidIsValid(result))
+ elog(ERROR, "could not find tuple for parent of relation %u", relid);
+
+ table_close(catalogRelation, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * get_partition_parent_worker
+ * Scan the pg_inherits relation to return the OID of the parent of the
+ * given relation
+ */
+static Oid
+get_partition_parent_worker(Relation inhRel, Oid relid)
+{
+ SysScanDesc scan;
+ ScanKeyData key[2];
+ Oid result = InvalidOid;
+ HeapTuple tuple;
+
+ ScanKeyInit(&key[0],
+ Anum_pg_inherits_inhrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ ScanKeyInit(&key[1],
+ Anum_pg_inherits_inhseqno,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(1));
+
+ scan = systable_beginscan(inhRel, InheritsRelidSeqnoIndexId, true,
+ NULL, 2, key);
+ tuple = systable_getnext(scan);
+ if (HeapTupleIsValid(tuple))
+ {
+ Form_pg_inherits form = (Form_pg_inherits) GETSTRUCT(tuple);
+
+ result = form->inhparent;
+ }
+
+ systable_endscan(scan);
+
+ return result;
+}
+
+/*
+ * get_partition_ancestors
+ * Obtain ancestors of given relation
+ *
+ * Returns a list of ancestors of the given relation.
+ *
+ * Note: Because this function assumes that the relation whose OID is passed
+ * as an argument and each ancestor will have precisely one parent, it should
+ * only be called when it is known that the relation is a partition.
+ */
+List *
+get_partition_ancestors(Oid relid)
+{
+ List *result = NIL;
+ Relation inhRel;
+
+ inhRel = table_open(InheritsRelationId, AccessShareLock);
+
+ get_partition_ancestors_worker(inhRel, relid, &result);
+
+ table_close(inhRel, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * get_partition_ancestors_worker
+ * recursive worker for get_partition_ancestors
+ */
+static void
+get_partition_ancestors_worker(Relation inhRel, Oid relid, List **ancestors)
+{
+ Oid parentOid;
+
+ /* Recursion ends at the topmost level, ie., when there's no parent */
+ parentOid = get_partition_parent_worker(inhRel, relid);
+ if (parentOid == InvalidOid)
+ return;
+
+ *ancestors = lappend_oid(*ancestors, parentOid);
+ get_partition_ancestors_worker(inhRel, parentOid, ancestors);
+}
+
+/*
+ * index_get_partition
+ * Return the OID of index of the given partition that is a child
+ * of the given index, or InvalidOid if there isn't one.
+ */
+Oid
+index_get_partition(Relation partition, Oid indexId)
+{
+ List *idxlist = RelationGetIndexList(partition);
+ ListCell *l;
+
+ foreach(l, idxlist)
+ {
+ Oid partIdx = lfirst_oid(l);
+ HeapTuple tup;
+ Form_pg_class classForm;
+ bool ispartition;
+
+ tup = SearchSysCache1(RELOID, ObjectIdGetDatum(partIdx));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for relation %u", partIdx);
+ classForm = (Form_pg_class) GETSTRUCT(tup);
+ ispartition = classForm->relispartition;
+ ReleaseSysCache(tup);
+ if (!ispartition)
+ continue;
+ if (get_partition_parent(partIdx) == indexId)
+ {
+ list_free(idxlist);
+ return partIdx;
+ }
+ }
+
+ list_free(idxlist);
+ return InvalidOid;
+}
+
+/*
+ * map_partition_varattnos - maps varattnos of all Vars in 'expr' (that have
+ * varno 'fromrel_varno') from the attnums of 'from_rel' to the attnums of
+ * 'to_rel', each of which may be either a leaf partition or a partitioned
+ * table, but both of which must be from the same partitioning hierarchy.
+ *
+ * We need this because even though all of the same column names must be
+ * present in all relations in the hierarchy, and they must also have the
+ * same types, the attnums may be different.
+ *
+ * Note: this will work on any node tree, so really the argument and result
+ * should be declared "Node *". But a substantial majority of the callers
+ * are working on Lists, so it's less messy to do the casts internally.
+ */
+List *
+map_partition_varattnos(List *expr, int fromrel_varno,
+ Relation to_rel, Relation from_rel)
+{
+ if (expr != NIL)
+ {
+ AttrMap *part_attmap;
+ bool found_whole_row;
+
+ part_attmap = build_attrmap_by_name(RelationGetDescr(to_rel),
+ RelationGetDescr(from_rel));
+ expr = (List *) map_variable_attnos((Node *) expr,
+ fromrel_varno, 0,
+ part_attmap,
+ RelationGetForm(to_rel)->reltype,
+ &found_whole_row);
+ /* Since we provided a to_rowtype, we may ignore found_whole_row. */
+ }
+
+ return expr;
+}
+
+/*
+ * Checks if any of the 'attnums' is a partition key attribute for rel
+ *
+ * Sets *used_in_expr if any of the 'attnums' is found to be referenced in some
+ * partition key expression. It's possible for a column to be both used
+ * directly and as part of an expression; if that happens, *used_in_expr may
+ * end up as either true or false. That's OK for current uses of this
+ * function, because *used_in_expr is only used to tailor the error message
+ * text.
+ */
+bool
+has_partition_attrs(Relation rel, Bitmapset *attnums, bool *used_in_expr)
+{
+ PartitionKey key;
+ int partnatts;
+ List *partexprs;
+ ListCell *partexprs_item;
+ int i;
+
+ if (attnums == NULL || rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
+ return false;
+
+ key = RelationGetPartitionKey(rel);
+ partnatts = get_partition_natts(key);
+ partexprs = get_partition_exprs(key);
+
+ partexprs_item = list_head(partexprs);
+ for (i = 0; i < partnatts; i++)
+ {
+ AttrNumber partattno = get_partition_col_attnum(key, i);
+
+ if (partattno != 0)
+ {
+ if (bms_is_member(partattno - FirstLowInvalidHeapAttributeNumber,
+ attnums))
+ {
+ if (used_in_expr)
+ *used_in_expr = false;
+ return true;
+ }
+ }
+ else
+ {
+ /* Arbitrary expression */
+ Node *expr = (Node *) lfirst(partexprs_item);
+ Bitmapset *expr_attrs = NULL;
+
+ /* Find all attributes referenced */
+ pull_varattnos(expr, 1, &expr_attrs);
+ partexprs_item = lnext(partexprs, partexprs_item);
+
+ if (bms_overlap(attnums, expr_attrs))
+ {
+ if (used_in_expr)
+ *used_in_expr = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/*
+ * get_default_partition_oid
+ *
+ * Given a relation OID, return the OID of the default partition, if one
+ * exists. Use get_default_oid_from_partdesc where possible, for
+ * efficiency.
+ */
+Oid
+get_default_partition_oid(Oid parentId)
+{
+ HeapTuple tuple;
+ Oid defaultPartId = InvalidOid;
+
+ tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(parentId));
+
+ if (HeapTupleIsValid(tuple))
+ {
+ Form_pg_partitioned_table part_table_form;
+
+ part_table_form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
+ defaultPartId = part_table_form->partdefid;
+ ReleaseSysCache(tuple);
+ }
+
+ return defaultPartId;
+}
+
+/*
+ * update_default_partition_oid
+ *
+ * Update pg_partitioned_table.partdefid with a new default partition OID.
+ */
+void
+update_default_partition_oid(Oid parentId, Oid defaultPartId)
+{
+ HeapTuple tuple;
+ Relation pg_partitioned_table;
+ Form_pg_partitioned_table part_table_form;
+
+ pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCacheCopy1(PARTRELID, ObjectIdGetDatum(parentId));
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for partition key of relation %u",
+ parentId);
+
+ part_table_form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
+ part_table_form->partdefid = defaultPartId;
+ CatalogTupleUpdate(pg_partitioned_table, &tuple->t_self, tuple);
+
+ heap_freetuple(tuple);
+ table_close(pg_partitioned_table, RowExclusiveLock);
+}
+
+/*
+ * get_proposed_default_constraint
+ *
+ * This function returns the negation of new_part_constraints, which
+ * would be an integral part of the default partition constraints after
+ * addition of the partition to which the new_part_constraints belongs.
+ */
+List *
+get_proposed_default_constraint(List *new_part_constraints)
+{
+ Expr *defPartConstraint;
+
+ defPartConstraint = make_ands_explicit(new_part_constraints);
+
+ /*
+ * Derive the partition constraints of default partition by negating the
+ * given partition constraints. The partition constraint never evaluates
+ * to NULL, so negating it like this is safe.
+ */
+ defPartConstraint = makeBoolExpr(NOT_EXPR,
+ list_make1(defPartConstraint),
+ -1);
+
+ /* Simplify, to put the negated expression into canonical form */
+ defPartConstraint =
+ (Expr *) eval_const_expressions(NULL,
+ (Node *) defPartConstraint);
+ defPartConstraint = canonicalize_qual(defPartConstraint, true);
+
+ return make_ands_implicit(defPartConstraint);
+}
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
new file mode 100644
index 0000000..6707fbc
--- /dev/null
+++ b/src/backend/catalog/pg_aggregate.c
@@ -0,0 +1,926 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_aggregate.c
+ * routines to support manipulation of the pg_aggregate relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_aggregate.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_language.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "miscadmin.h"
+#include "parser/parse_coerce.h"
+#include "parser/parse_func.h"
+#include "parser/parse_oper.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+
+static Oid lookup_agg_function(List *fnName, int nargs, Oid *input_types,
+ Oid variadicArgType,
+ Oid *rettype);
+
+
+/*
+ * AggregateCreate
+ */
+ObjectAddress
+AggregateCreate(const char *aggName,
+ Oid aggNamespace,
+ bool replace,
+ char aggKind,
+ int numArgs,
+ int numDirectArgs,
+ oidvector *parameterTypes,
+ Datum allParameterTypes,
+ Datum parameterModes,
+ Datum parameterNames,
+ List *parameterDefaults,
+ Oid variadicArgType,
+ List *aggtransfnName,
+ List *aggfinalfnName,
+ List *aggcombinefnName,
+ List *aggserialfnName,
+ List *aggdeserialfnName,
+ List *aggmtransfnName,
+ List *aggminvtransfnName,
+ List *aggmfinalfnName,
+ bool finalfnExtraArgs,
+ bool mfinalfnExtraArgs,
+ char finalfnModify,
+ char mfinalfnModify,
+ List *aggsortopName,
+ Oid aggTransType,
+ int32 aggTransSpace,
+ Oid aggmTransType,
+ int32 aggmTransSpace,
+ const char *agginitval,
+ const char *aggminitval,
+ char proparallel)
+{
+ Relation aggdesc;
+ HeapTuple tup;
+ HeapTuple oldtup;
+ bool nulls[Natts_pg_aggregate];
+ Datum values[Natts_pg_aggregate];
+ bool replaces[Natts_pg_aggregate];
+ Form_pg_proc proc;
+ Oid transfn;
+ Oid finalfn = InvalidOid; /* can be omitted */
+ Oid combinefn = InvalidOid; /* can be omitted */
+ Oid serialfn = InvalidOid; /* can be omitted */
+ Oid deserialfn = InvalidOid; /* can be omitted */
+ Oid mtransfn = InvalidOid; /* can be omitted */
+ Oid minvtransfn = InvalidOid; /* can be omitted */
+ Oid mfinalfn = InvalidOid; /* can be omitted */
+ Oid sortop = InvalidOid; /* can be omitted */
+ Oid *aggArgTypes = parameterTypes->values;
+ bool mtransIsStrict = false;
+ Oid rettype;
+ Oid finaltype;
+ Oid fnArgs[FUNC_MAX_ARGS];
+ int nargs_transfn;
+ int nargs_finalfn;
+ Oid procOid;
+ TupleDesc tupDesc;
+ char *detailmsg;
+ int i;
+ ObjectAddress myself,
+ referenced;
+ AclResult aclresult;
+
+ /* sanity checks (caller should have caught these) */
+ if (!aggName)
+ elog(ERROR, "no aggregate name supplied");
+
+ if (!aggtransfnName)
+ elog(ERROR, "aggregate must have a transition function");
+
+ if (numDirectArgs < 0 || numDirectArgs > numArgs)
+ elog(ERROR, "incorrect number of direct arguments for aggregate");
+
+ /*
+ * Aggregates can have at most FUNC_MAX_ARGS-1 args, else the transfn
+ * and/or finalfn will be unrepresentable in pg_proc. We must check now
+ * to protect fixed-size arrays here and possibly in called functions.
+ */
+ if (numArgs < 0 || numArgs > FUNC_MAX_ARGS - 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
+ errmsg_plural("aggregates cannot have more than %d argument",
+ "aggregates cannot have more than %d arguments",
+ FUNC_MAX_ARGS - 1,
+ FUNC_MAX_ARGS - 1)));
+
+ /*
+ * If transtype is polymorphic, must have polymorphic argument also; else
+ * we will have no way to deduce the actual transtype.
+ */
+ detailmsg = check_valid_polymorphic_signature(aggTransType,
+ aggArgTypes,
+ numArgs);
+ if (detailmsg)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("cannot determine transition data type"),
+ errdetail_internal("%s", detailmsg)));
+
+ /*
+ * Likewise for moving-aggregate transtype, if any
+ */
+ if (OidIsValid(aggmTransType))
+ {
+ detailmsg = check_valid_polymorphic_signature(aggmTransType,
+ aggArgTypes,
+ numArgs);
+ if (detailmsg)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("cannot determine transition data type"),
+ errdetail_internal("%s", detailmsg)));
+ }
+
+ /*
+ * An ordered-set aggregate that is VARIADIC must be VARIADIC ANY. In
+ * principle we could support regular variadic types, but it would make
+ * things much more complicated because we'd have to assemble the correct
+ * subsets of arguments into array values. Since no standard aggregates
+ * have use for such a case, we aren't bothering for now.
+ */
+ if (AGGKIND_IS_ORDERED_SET(aggKind) && OidIsValid(variadicArgType) &&
+ variadicArgType != ANYOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("a variadic ordered-set aggregate must use VARIADIC type ANY")));
+
+ /*
+ * If it's a hypothetical-set aggregate, there must be at least as many
+ * direct arguments as aggregated ones, and the last N direct arguments
+ * must match the aggregated ones in type. (We have to check this again
+ * when the aggregate is called, in case ANY is involved, but it makes
+ * sense to reject the aggregate definition now if the declared arg types
+ * don't match up.) It's unconditionally OK if numDirectArgs == numArgs,
+ * indicating that the grammar merged identical VARIADIC entries from both
+ * lists. Otherwise, if the agg is VARIADIC, then we had VARIADIC only on
+ * the aggregated side, which is not OK. Otherwise, insist on the last N
+ * parameter types on each side matching exactly.
+ */
+ if (aggKind == AGGKIND_HYPOTHETICAL &&
+ numDirectArgs < numArgs)
+ {
+ int numAggregatedArgs = numArgs - numDirectArgs;
+
+ if (OidIsValid(variadicArgType) ||
+ numDirectArgs < numAggregatedArgs ||
+ memcmp(aggArgTypes + (numDirectArgs - numAggregatedArgs),
+ aggArgTypes + numDirectArgs,
+ numAggregatedArgs * sizeof(Oid)) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("a hypothetical-set aggregate must have direct arguments matching its aggregated arguments")));
+ }
+
+ /*
+ * Find the transfn. For ordinary aggs, it takes the transtype plus all
+ * aggregate arguments. For ordered-set aggs, it takes the transtype plus
+ * all aggregated args, but not direct args. However, we have to treat
+ * specially the case where a trailing VARIADIC item is considered to
+ * cover both direct and aggregated args.
+ */
+ if (AGGKIND_IS_ORDERED_SET(aggKind))
+ {
+ if (numDirectArgs < numArgs)
+ nargs_transfn = numArgs - numDirectArgs + 1;
+ else
+ {
+ /* special case with VARIADIC last arg */
+ Assert(variadicArgType != InvalidOid);
+ nargs_transfn = 2;
+ }
+ fnArgs[0] = aggTransType;
+ memcpy(fnArgs + 1, aggArgTypes + (numArgs - (nargs_transfn - 1)),
+ (nargs_transfn - 1) * sizeof(Oid));
+ }
+ else
+ {
+ nargs_transfn = numArgs + 1;
+ fnArgs[0] = aggTransType;
+ memcpy(fnArgs + 1, aggArgTypes, numArgs * sizeof(Oid));
+ }
+ transfn = lookup_agg_function(aggtransfnName, nargs_transfn,
+ fnArgs, variadicArgType,
+ &rettype);
+
+ /*
+ * Return type of transfn (possibly after refinement by
+ * enforce_generic_type_consistency, if transtype isn't polymorphic) must
+ * exactly match declared transtype.
+ *
+ * In the non-polymorphic-transtype case, it might be okay to allow a
+ * rettype that's binary-coercible to transtype, but I'm not quite
+ * convinced that it's either safe or useful. When transtype is
+ * polymorphic we *must* demand exact equality.
+ */
+ if (rettype != aggTransType)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("return type of transition function %s is not %s",
+ NameListToString(aggtransfnName),
+ format_type_be(aggTransType))));
+
+ tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(transfn));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for function %u", transfn);
+ proc = (Form_pg_proc) GETSTRUCT(tup);
+
+ /*
+ * If the transfn is strict and the initval is NULL, make sure first input
+ * type and transtype are the same (or at least binary-compatible), so
+ * that it's OK to use the first input value as the initial transValue.
+ */
+ if (proc->proisstrict && agginitval == NULL)
+ {
+ if (numArgs < 1 ||
+ !IsBinaryCoercible(aggArgTypes[0], aggTransType))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("must not omit initial value when transition function is strict and transition type is not compatible with input type")));
+ }
+
+ ReleaseSysCache(tup);
+
+ /* handle moving-aggregate transfn, if supplied */
+ if (aggmtransfnName)
+ {
+ /*
+ * The arguments are the same as for the regular transfn, except that
+ * the transition data type might be different. So re-use the fnArgs
+ * values set up above, except for that one.
+ */
+ Assert(OidIsValid(aggmTransType));
+ fnArgs[0] = aggmTransType;
+
+ mtransfn = lookup_agg_function(aggmtransfnName, nargs_transfn,
+ fnArgs, variadicArgType,
+ &rettype);
+
+ /* As above, return type must exactly match declared mtranstype. */
+ if (rettype != aggmTransType)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("return type of transition function %s is not %s",
+ NameListToString(aggmtransfnName),
+ format_type_be(aggmTransType))));
+
+ tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(mtransfn));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for function %u", mtransfn);
+ proc = (Form_pg_proc) GETSTRUCT(tup);
+
+ /*
+ * If the mtransfn is strict and the minitval is NULL, check first
+ * input type and mtranstype are binary-compatible.
+ */
+ if (proc->proisstrict && aggminitval == NULL)
+ {
+ if (numArgs < 1 ||
+ !IsBinaryCoercible(aggArgTypes[0], aggmTransType))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("must not omit initial value when transition function is strict and transition type is not compatible with input type")));
+ }
+
+ /* Remember if mtransfn is strict; we may need this below */
+ mtransIsStrict = proc->proisstrict;
+
+ ReleaseSysCache(tup);
+ }
+
+ /* handle minvtransfn, if supplied */
+ if (aggminvtransfnName)
+ {
+ /*
+ * This must have the same number of arguments with the same types as
+ * the forward transition function, so just re-use the fnArgs data.
+ */
+ Assert(aggmtransfnName);
+
+ minvtransfn = lookup_agg_function(aggminvtransfnName, nargs_transfn,
+ fnArgs, variadicArgType,
+ &rettype);
+
+ /* As above, return type must exactly match declared mtranstype. */
+ if (rettype != aggmTransType)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("return type of inverse transition function %s is not %s",
+ NameListToString(aggminvtransfnName),
+ format_type_be(aggmTransType))));
+
+ tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(minvtransfn));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for function %u", minvtransfn);
+ proc = (Form_pg_proc) GETSTRUCT(tup);
+
+ /*
+ * We require the strictness settings of the forward and inverse
+ * transition functions to agree. This saves having to handle
+ * assorted special cases at execution time.
+ */
+ if (proc->proisstrict != mtransIsStrict)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("strictness of aggregate's forward and inverse transition functions must match")));
+
+ ReleaseSysCache(tup);
+ }
+
+ /* handle finalfn, if supplied */
+ if (aggfinalfnName)
+ {
+ /*
+ * If finalfnExtraArgs is specified, the transfn takes the transtype
+ * plus all args; otherwise, it just takes the transtype plus any
+ * direct args. (Non-direct args are useless at runtime, and are
+ * actually passed as NULLs, but we may need them in the function
+ * signature to allow resolution of a polymorphic agg's result type.)
+ */
+ Oid ffnVariadicArgType = variadicArgType;
+
+ fnArgs[0] = aggTransType;
+ memcpy(fnArgs + 1, aggArgTypes, numArgs * sizeof(Oid));
+ if (finalfnExtraArgs)
+ nargs_finalfn = numArgs + 1;
+ else
+ {
+ nargs_finalfn = numDirectArgs + 1;
+ if (numDirectArgs < numArgs)
+ {
+ /* variadic argument doesn't affect finalfn */
+ ffnVariadicArgType = InvalidOid;
+ }
+ }
+
+ finalfn = lookup_agg_function(aggfinalfnName, nargs_finalfn,
+ fnArgs, ffnVariadicArgType,
+ &finaltype);
+
+ /*
+ * When finalfnExtraArgs is specified, the finalfn will certainly be
+ * passed at least one null argument, so complain if it's strict.
+ * Nothing bad would happen at runtime (you'd just get a null result),
+ * but it's surely not what the user wants, so let's complain now.
+ */
+ if (finalfnExtraArgs && func_strict(finalfn))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("final function with extra arguments must not be declared STRICT")));
+ }
+ else
+ {
+ /*
+ * If no finalfn, aggregate result type is type of the state value
+ */
+ finaltype = aggTransType;
+ }
+ Assert(OidIsValid(finaltype));
+
+ /* handle the combinefn, if supplied */
+ if (aggcombinefnName)
+ {
+ Oid combineType;
+
+ /*
+ * Combine function must have 2 arguments, each of which is the trans
+ * type. VARIADIC doesn't affect it.
+ */
+ fnArgs[0] = aggTransType;
+ fnArgs[1] = aggTransType;
+
+ combinefn = lookup_agg_function(aggcombinefnName, 2,
+ fnArgs, InvalidOid,
+ &combineType);
+
+ /* Ensure the return type matches the aggregate's trans type */
+ if (combineType != aggTransType)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("return type of combine function %s is not %s",
+ NameListToString(aggcombinefnName),
+ format_type_be(aggTransType))));
+
+ /*
+ * A combine function to combine INTERNAL states must accept nulls and
+ * ensure that the returned state is in the correct memory context. We
+ * cannot directly check the latter, but we can check the former.
+ */
+ if (aggTransType == INTERNALOID && func_strict(combinefn))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("combine function with transition type %s must not be declared STRICT",
+ format_type_be(aggTransType))));
+ }
+
+ /*
+ * Validate the serialization function, if present.
+ */
+ if (aggserialfnName)
+ {
+ /* signature is always serialize(internal) returns bytea */
+ fnArgs[0] = INTERNALOID;
+
+ serialfn = lookup_agg_function(aggserialfnName, 1,
+ fnArgs, InvalidOid,
+ &rettype);
+
+ if (rettype != BYTEAOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("return type of serialization function %s is not %s",
+ NameListToString(aggserialfnName),
+ format_type_be(BYTEAOID))));
+ }
+
+ /*
+ * Validate the deserialization function, if present.
+ */
+ if (aggdeserialfnName)
+ {
+ /* signature is always deserialize(bytea, internal) returns internal */
+ fnArgs[0] = BYTEAOID;
+ fnArgs[1] = INTERNALOID; /* dummy argument for type safety */
+
+ deserialfn = lookup_agg_function(aggdeserialfnName, 2,
+ fnArgs, InvalidOid,
+ &rettype);
+
+ if (rettype != INTERNALOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("return type of deserialization function %s is not %s",
+ NameListToString(aggdeserialfnName),
+ format_type_be(INTERNALOID))));
+ }
+
+ /*
+ * If finaltype (i.e. aggregate return type) is polymorphic, inputs must
+ * be polymorphic also, else parser will fail to deduce result type.
+ * (Note: given the previous test on transtype and inputs, this cannot
+ * happen, unless someone has snuck a finalfn definition into the catalogs
+ * that itself violates the rule against polymorphic result with no
+ * polymorphic input.)
+ */
+ detailmsg = check_valid_polymorphic_signature(finaltype,
+ aggArgTypes,
+ numArgs);
+ if (detailmsg)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("cannot determine result data type"),
+ errdetail_internal("%s", detailmsg)));
+
+ /*
+ * Also, the return type can't be INTERNAL unless there's at least one
+ * INTERNAL argument. This is the same type-safety restriction we enforce
+ * for regular functions, but at the level of aggregates. We must test
+ * this explicitly because we allow INTERNAL as the transtype.
+ */
+ detailmsg = check_valid_internal_signature(finaltype,
+ aggArgTypes,
+ numArgs);
+ if (detailmsg)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("unsafe use of pseudo-type \"internal\""),
+ errdetail_internal("%s", detailmsg)));
+
+ /*
+ * If a moving-aggregate implementation is supplied, look up its finalfn
+ * if any, and check that the implied aggregate result type matches the
+ * plain implementation.
+ */
+ if (OidIsValid(aggmTransType))
+ {
+ /* handle finalfn, if supplied */
+ if (aggmfinalfnName)
+ {
+ /*
+ * The arguments are figured the same way as for the regular
+ * finalfn, but using aggmTransType and mfinalfnExtraArgs.
+ */
+ Oid ffnVariadicArgType = variadicArgType;
+
+ fnArgs[0] = aggmTransType;
+ memcpy(fnArgs + 1, aggArgTypes, numArgs * sizeof(Oid));
+ if (mfinalfnExtraArgs)
+ nargs_finalfn = numArgs + 1;
+ else
+ {
+ nargs_finalfn = numDirectArgs + 1;
+ if (numDirectArgs < numArgs)
+ {
+ /* variadic argument doesn't affect finalfn */
+ ffnVariadicArgType = InvalidOid;
+ }
+ }
+
+ mfinalfn = lookup_agg_function(aggmfinalfnName, nargs_finalfn,
+ fnArgs, ffnVariadicArgType,
+ &rettype);
+
+ /* As above, check strictness if mfinalfnExtraArgs is given */
+ if (mfinalfnExtraArgs && func_strict(mfinalfn))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("final function with extra arguments must not be declared STRICT")));
+ }
+ else
+ {
+ /*
+ * If no finalfn, aggregate result type is type of the state value
+ */
+ rettype = aggmTransType;
+ }
+ Assert(OidIsValid(rettype));
+ if (rettype != finaltype)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("moving-aggregate implementation returns type %s, but plain implementation returns type %s",
+ format_type_be(rettype),
+ format_type_be(finaltype))));
+ }
+
+ /* handle sortop, if supplied */
+ if (aggsortopName)
+ {
+ if (numArgs != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("sort operator can only be specified for single-argument aggregates")));
+ sortop = LookupOperName(NULL, aggsortopName,
+ aggArgTypes[0], aggArgTypes[0],
+ false, -1);
+ }
+
+ /*
+ * permission checks on used types
+ */
+ for (i = 0; i < numArgs; i++)
+ {
+ aclresult = pg_type_aclcheck(aggArgTypes[i], GetUserId(), ACL_USAGE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error_type(aclresult, aggArgTypes[i]);
+ }
+
+ aclresult = pg_type_aclcheck(aggTransType, GetUserId(), ACL_USAGE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error_type(aclresult, aggTransType);
+
+ if (OidIsValid(aggmTransType))
+ {
+ aclresult = pg_type_aclcheck(aggmTransType, GetUserId(), ACL_USAGE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error_type(aclresult, aggmTransType);
+ }
+
+ aclresult = pg_type_aclcheck(finaltype, GetUserId(), ACL_USAGE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error_type(aclresult, finaltype);
+
+
+ /*
+ * Everything looks okay. Try to create the pg_proc entry for the
+ * aggregate. (This could fail if there's already a conflicting entry.)
+ */
+
+ myself = ProcedureCreate(aggName,
+ aggNamespace,
+ replace, /* maybe replacement */
+ false, /* doesn't return a set */
+ finaltype, /* returnType */
+ GetUserId(), /* proowner */
+ INTERNALlanguageId, /* languageObjectId */
+ InvalidOid, /* no validator */
+ "aggregate_dummy", /* placeholder proc */
+ NULL, /* probin */
+ PROKIND_AGGREGATE,
+ false, /* security invoker (currently not
+ * definable for agg) */
+ false, /* isLeakProof */
+ false, /* isStrict (not needed for agg) */
+ PROVOLATILE_IMMUTABLE, /* volatility (not needed
+ * for agg) */
+ proparallel,
+ parameterTypes, /* paramTypes */
+ allParameterTypes, /* allParamTypes */
+ parameterModes, /* parameterModes */
+ parameterNames, /* parameterNames */
+ parameterDefaults, /* parameterDefaults */
+ PointerGetDatum(NULL), /* trftypes */
+ PointerGetDatum(NULL), /* proconfig */
+ InvalidOid, /* no prosupport */
+ 1, /* procost */
+ 0); /* prorows */
+ procOid = myself.objectId;
+
+ /*
+ * Okay to create the pg_aggregate entry.
+ */
+ aggdesc = table_open(AggregateRelationId, RowExclusiveLock);
+ tupDesc = aggdesc->rd_att;
+
+ /* initialize nulls and values */
+ for (i = 0; i < Natts_pg_aggregate; i++)
+ {
+ nulls[i] = false;
+ values[i] = (Datum) NULL;
+ replaces[i] = true;
+ }
+ values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid);
+ values[Anum_pg_aggregate_aggkind - 1] = CharGetDatum(aggKind);
+ values[Anum_pg_aggregate_aggnumdirectargs - 1] = Int16GetDatum(numDirectArgs);
+ values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn);
+ values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
+ values[Anum_pg_aggregate_aggcombinefn - 1] = ObjectIdGetDatum(combinefn);
+ values[Anum_pg_aggregate_aggserialfn - 1] = ObjectIdGetDatum(serialfn);
+ values[Anum_pg_aggregate_aggdeserialfn - 1] = ObjectIdGetDatum(deserialfn);
+ values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn);
+ values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn);
+ values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn);
+ values[Anum_pg_aggregate_aggfinalextra - 1] = BoolGetDatum(finalfnExtraArgs);
+ values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs);
+ values[Anum_pg_aggregate_aggfinalmodify - 1] = CharGetDatum(finalfnModify);
+ values[Anum_pg_aggregate_aggmfinalmodify - 1] = CharGetDatum(mfinalfnModify);
+ values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
+ values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
+ values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
+ values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType);
+ values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace);
+ if (agginitval)
+ values[Anum_pg_aggregate_agginitval - 1] = CStringGetTextDatum(agginitval);
+ else
+ nulls[Anum_pg_aggregate_agginitval - 1] = true;
+ if (aggminitval)
+ values[Anum_pg_aggregate_aggminitval - 1] = CStringGetTextDatum(aggminitval);
+ else
+ nulls[Anum_pg_aggregate_aggminitval - 1] = true;
+
+ if (replace)
+ oldtup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(procOid));
+ else
+ oldtup = NULL;
+
+ if (HeapTupleIsValid(oldtup))
+ {
+ Form_pg_aggregate oldagg = (Form_pg_aggregate) GETSTRUCT(oldtup);
+
+ /*
+ * If we're replacing an existing entry, we need to validate that
+ * we're not changing anything that would break callers. Specifically
+ * we must not change aggkind or aggnumdirectargs, which affect how an
+ * aggregate call is treated in parse analysis.
+ */
+ if (aggKind != oldagg->aggkind)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot change routine kind"),
+ (oldagg->aggkind == AGGKIND_NORMAL ?
+ errdetail("\"%s\" is an ordinary aggregate function.", aggName) :
+ oldagg->aggkind == AGGKIND_ORDERED_SET ?
+ errdetail("\"%s\" is an ordered-set aggregate.", aggName) :
+ oldagg->aggkind == AGGKIND_HYPOTHETICAL ?
+ errdetail("\"%s\" is a hypothetical-set aggregate.", aggName) :
+ 0)));
+ if (numDirectArgs != oldagg->aggnumdirectargs)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("cannot change number of direct arguments of an aggregate function")));
+
+ replaces[Anum_pg_aggregate_aggfnoid - 1] = false;
+ replaces[Anum_pg_aggregate_aggkind - 1] = false;
+ replaces[Anum_pg_aggregate_aggnumdirectargs - 1] = false;
+
+ tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
+ CatalogTupleUpdate(aggdesc, &tup->t_self, tup);
+ ReleaseSysCache(oldtup);
+ }
+ else
+ {
+ tup = heap_form_tuple(tupDesc, values, nulls);
+ CatalogTupleInsert(aggdesc, tup);
+ }
+
+ table_close(aggdesc, RowExclusiveLock);
+
+ /*
+ * Create dependencies for the aggregate (above and beyond those already
+ * made by ProcedureCreate). Note: we don't need an explicit dependency
+ * on aggTransType since we depend on it indirectly through transfn.
+ * Likewise for aggmTransType using the mtransfn, if it exists.
+ *
+ * If we're replacing an existing definition, ProcedureCreate deleted all
+ * our existing dependencies, so we have to do the same things here either
+ * way.
+ */
+
+ /* Depends on transition function */
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = transfn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* Depends on final function, if any */
+ if (OidIsValid(finalfn))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = finalfn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Depends on combine function, if any */
+ if (OidIsValid(combinefn))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = combinefn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Depends on serialization function, if any */
+ if (OidIsValid(serialfn))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = serialfn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Depends on deserialization function, if any */
+ if (OidIsValid(deserialfn))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = deserialfn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Depends on forward transition function, if any */
+ if (OidIsValid(mtransfn))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = mtransfn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Depends on inverse transition function, if any */
+ if (OidIsValid(minvtransfn))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = minvtransfn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Depends on final function, if any */
+ if (OidIsValid(mfinalfn))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = mfinalfn;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Depends on sort operator, if any */
+ if (OidIsValid(sortop))
+ {
+ referenced.classId = OperatorRelationId;
+ referenced.objectId = sortop;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ return myself;
+}
+
+/*
+ * lookup_agg_function
+ * common code for finding aggregate support functions
+ *
+ * fnName: possibly-schema-qualified function name
+ * nargs, input_types: expected function argument types
+ * variadicArgType: type of variadic argument if any, else InvalidOid
+ *
+ * Returns OID of function, and stores its return type into *rettype
+ *
+ * NB: must not scribble on input_types[], as we may re-use those
+ */
+static Oid
+lookup_agg_function(List *fnName,
+ int nargs,
+ Oid *input_types,
+ Oid variadicArgType,
+ Oid *rettype)
+{
+ Oid fnOid;
+ bool retset;
+ int nvargs;
+ Oid vatype;
+ Oid *true_oid_array;
+ FuncDetailCode fdresult;
+ AclResult aclresult;
+ int i;
+
+ /*
+ * func_get_detail looks up the function in the catalogs, does
+ * disambiguation for polymorphic functions, handles inheritance, and
+ * returns the funcid and type and set or singleton status of the
+ * function's return value. it also returns the true argument types to
+ * the function.
+ */
+ fdresult = func_get_detail(fnName, NIL, NIL,
+ nargs, input_types, false, false,
+ &fnOid, rettype, &retset,
+ &nvargs, &vatype,
+ &true_oid_array, NULL);
+
+ /* only valid case is a normal function not returning a set */
+ if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("function %s does not exist",
+ func_signature_string(fnName, nargs,
+ NIL, input_types))));
+ if (retset)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("function %s returns a set",
+ func_signature_string(fnName, nargs,
+ NIL, input_types))));
+
+ /*
+ * If the agg is declared to take VARIADIC ANY, the underlying functions
+ * had better be declared that way too, else they may receive too many
+ * parameters; but func_get_detail would have been happy with plain ANY.
+ * (Probably nothing very bad would happen, but it wouldn't work as the
+ * user expects.) Other combinations should work without any special
+ * pushups, given that we told func_get_detail not to expand VARIADIC.
+ */
+ if (variadicArgType == ANYOID && vatype != ANYOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("function %s must accept VARIADIC ANY to be used in this aggregate",
+ func_signature_string(fnName, nargs,
+ NIL, input_types))));
+
+ /*
+ * If there are any polymorphic types involved, enforce consistency, and
+ * possibly refine the result type. It's OK if the result is still
+ * polymorphic at this point, though.
+ */
+ *rettype = enforce_generic_type_consistency(input_types,
+ true_oid_array,
+ nargs,
+ *rettype,
+ true);
+
+ /*
+ * func_get_detail will find functions requiring run-time argument type
+ * coercion, but nodeAgg.c isn't prepared to deal with that
+ */
+ for (i = 0; i < nargs; i++)
+ {
+ if (!IsBinaryCoercible(input_types[i], true_oid_array[i]))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("function %s requires run-time type coercion",
+ func_signature_string(fnName, nargs,
+ NIL, true_oid_array))));
+ }
+
+ /* Check aggregate creator has permission to call the function */
+ aclresult = pg_proc_aclcheck(fnOid, GetUserId(), ACL_EXECUTE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(fnOid));
+
+ return fnOid;
+}
diff --git a/src/backend/catalog/pg_aggregate_d.h b/src/backend/catalog/pg_aggregate_d.h
new file mode 100644
index 0000000..a00cd1f
--- /dev/null
+++ b/src/backend/catalog/pg_aggregate_d.h
@@ -0,0 +1,77 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_aggregate_d.h
+ * Macro definitions for pg_aggregate
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AGGREGATE_D_H
+#define PG_AGGREGATE_D_H
+
+#define AggregateRelationId 2600
+
+#define Anum_pg_aggregate_aggfnoid 1
+#define Anum_pg_aggregate_aggkind 2
+#define Anum_pg_aggregate_aggnumdirectargs 3
+#define Anum_pg_aggregate_aggtransfn 4
+#define Anum_pg_aggregate_aggfinalfn 5
+#define Anum_pg_aggregate_aggcombinefn 6
+#define Anum_pg_aggregate_aggserialfn 7
+#define Anum_pg_aggregate_aggdeserialfn 8
+#define Anum_pg_aggregate_aggmtransfn 9
+#define Anum_pg_aggregate_aggminvtransfn 10
+#define Anum_pg_aggregate_aggmfinalfn 11
+#define Anum_pg_aggregate_aggfinalextra 12
+#define Anum_pg_aggregate_aggmfinalextra 13
+#define Anum_pg_aggregate_aggfinalmodify 14
+#define Anum_pg_aggregate_aggmfinalmodify 15
+#define Anum_pg_aggregate_aggsortop 16
+#define Anum_pg_aggregate_aggtranstype 17
+#define Anum_pg_aggregate_aggtransspace 18
+#define Anum_pg_aggregate_aggmtranstype 19
+#define Anum_pg_aggregate_aggmtransspace 20
+#define Anum_pg_aggregate_agginitval 21
+#define Anum_pg_aggregate_aggminitval 22
+
+#define Natts_pg_aggregate 22
+
+
+/*
+ * Symbolic values for aggkind column. We distinguish normal aggregates
+ * from ordered-set aggregates (which have two sets of arguments, namely
+ * direct and aggregated arguments) and from hypothetical-set aggregates
+ * (which are a subclass of ordered-set aggregates in which the last
+ * direct arguments have to match up in number and datatypes with the
+ * aggregated arguments).
+ */
+#define AGGKIND_NORMAL 'n'
+#define AGGKIND_ORDERED_SET 'o'
+#define AGGKIND_HYPOTHETICAL 'h'
+
+/* Use this macro to test for "ordered-set agg including hypothetical case" */
+#define AGGKIND_IS_ORDERED_SET(kind) ((kind) != AGGKIND_NORMAL)
+
+/*
+ * Symbolic values for aggfinalmodify and aggmfinalmodify columns.
+ * Preferably, finalfns do not modify the transition state value at all,
+ * but in some cases that would cost too much performance. We distinguish
+ * "pure read only" and "trashes it arbitrarily" cases, as well as the
+ * intermediate case where multiple finalfn calls are allowed but the
+ * transfn cannot be applied anymore after the first finalfn call.
+ */
+#define AGGMODIFY_READ_ONLY 'r'
+#define AGGMODIFY_SHAREABLE 's'
+#define AGGMODIFY_READ_WRITE 'w'
+
+
+#endif /* PG_AGGREGATE_D_H */
diff --git a/src/backend/catalog/pg_am_d.h b/src/backend/catalog/pg_am_d.h
new file mode 100644
index 0000000..2b6b941
--- /dev/null
+++ b/src/backend/catalog/pg_am_d.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_am_d.h
+ * Macro definitions for pg_am
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AM_D_H
+#define PG_AM_D_H
+
+#define AccessMethodRelationId 2601
+
+#define Anum_pg_am_oid 1
+#define Anum_pg_am_amname 2
+#define Anum_pg_am_amhandler 3
+#define Anum_pg_am_amtype 4
+
+#define Natts_pg_am 4
+
+
+/*
+ * Allowed values for amtype
+ */
+#define AMTYPE_INDEX 'i' /* index access method */
+#define AMTYPE_TABLE 't' /* table access method */
+
+#define HEAP_TABLE_AM_OID 2
+#define BTREE_AM_OID 403
+#define HASH_AM_OID 405
+#define GIST_AM_OID 783
+#define GIN_AM_OID 2742
+#define SPGIST_AM_OID 4000
+#define BRIN_AM_OID 3580
+
+#endif /* PG_AM_D_H */
diff --git a/src/backend/catalog/pg_amop_d.h b/src/backend/catalog/pg_amop_d.h
new file mode 100644
index 0000000..7d34ee6
--- /dev/null
+++ b/src/backend/catalog/pg_amop_d.h
@@ -0,0 +1,41 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_amop_d.h
+ * Macro definitions for pg_amop
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AMOP_D_H
+#define PG_AMOP_D_H
+
+#define AccessMethodOperatorRelationId 2602
+
+#define Anum_pg_amop_oid 1
+#define Anum_pg_amop_amopfamily 2
+#define Anum_pg_amop_amoplefttype 3
+#define Anum_pg_amop_amoprighttype 4
+#define Anum_pg_amop_amopstrategy 5
+#define Anum_pg_amop_amoppurpose 6
+#define Anum_pg_amop_amopopr 7
+#define Anum_pg_amop_amopmethod 8
+#define Anum_pg_amop_amopsortfamily 9
+
+#define Natts_pg_amop 9
+
+
+/* allowed values of amoppurpose: */
+#define AMOP_SEARCH 's' /* operator is for search */
+#define AMOP_ORDER 'o' /* operator is for ordering */
+
+
+#endif /* PG_AMOP_D_H */
diff --git a/src/backend/catalog/pg_amproc_d.h b/src/backend/catalog/pg_amproc_d.h
new file mode 100644
index 0000000..9b51d1d
--- /dev/null
+++ b/src/backend/catalog/pg_amproc_d.h
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_amproc_d.h
+ * Macro definitions for pg_amproc
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AMPROC_D_H
+#define PG_AMPROC_D_H
+
+#define AccessMethodProcedureRelationId 2603
+
+#define Anum_pg_amproc_oid 1
+#define Anum_pg_amproc_amprocfamily 2
+#define Anum_pg_amproc_amproclefttype 3
+#define Anum_pg_amproc_amprocrighttype 4
+#define Anum_pg_amproc_amprocnum 5
+#define Anum_pg_amproc_amproc 6
+
+#define Natts_pg_amproc 6
+
+
+#endif /* PG_AMPROC_D_H */
diff --git a/src/backend/catalog/pg_attrdef_d.h b/src/backend/catalog/pg_attrdef_d.h
new file mode 100644
index 0000000..b426981
--- /dev/null
+++ b/src/backend/catalog/pg_attrdef_d.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_attrdef_d.h
+ * Macro definitions for pg_attrdef
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_ATTRDEF_D_H
+#define PG_ATTRDEF_D_H
+
+#define AttrDefaultRelationId 2604
+
+#define Anum_pg_attrdef_oid 1
+#define Anum_pg_attrdef_adrelid 2
+#define Anum_pg_attrdef_adnum 3
+#define Anum_pg_attrdef_adbin 4
+
+#define Natts_pg_attrdef 4
+
+
+#endif /* PG_ATTRDEF_D_H */
diff --git a/src/backend/catalog/pg_attribute_d.h b/src/backend/catalog/pg_attribute_d.h
new file mode 100644
index 0000000..d736b6c
--- /dev/null
+++ b/src/backend/catalog/pg_attribute_d.h
@@ -0,0 +1,59 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_attribute_d.h
+ * Macro definitions for pg_attribute
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_ATTRIBUTE_D_H
+#define PG_ATTRIBUTE_D_H
+
+#define AttributeRelationId 1249
+#define AttributeRelation_Rowtype_Id 75
+
+#define Anum_pg_attribute_attrelid 1
+#define Anum_pg_attribute_attname 2
+#define Anum_pg_attribute_atttypid 3
+#define Anum_pg_attribute_attstattarget 4
+#define Anum_pg_attribute_attlen 5
+#define Anum_pg_attribute_attnum 6
+#define Anum_pg_attribute_attndims 7
+#define Anum_pg_attribute_attcacheoff 8
+#define Anum_pg_attribute_atttypmod 9
+#define Anum_pg_attribute_attbyval 10
+#define Anum_pg_attribute_attstorage 11
+#define Anum_pg_attribute_attalign 12
+#define Anum_pg_attribute_attnotnull 13
+#define Anum_pg_attribute_atthasdef 14
+#define Anum_pg_attribute_atthasmissing 15
+#define Anum_pg_attribute_attidentity 16
+#define Anum_pg_attribute_attgenerated 17
+#define Anum_pg_attribute_attisdropped 18
+#define Anum_pg_attribute_attislocal 19
+#define Anum_pg_attribute_attinhcount 20
+#define Anum_pg_attribute_attcollation 21
+#define Anum_pg_attribute_attacl 22
+#define Anum_pg_attribute_attoptions 23
+#define Anum_pg_attribute_attfdwoptions 24
+#define Anum_pg_attribute_attmissingval 25
+
+#define Natts_pg_attribute 25
+
+
+#define ATTRIBUTE_IDENTITY_ALWAYS 'a'
+#define ATTRIBUTE_IDENTITY_BY_DEFAULT 'd'
+
+#define ATTRIBUTE_GENERATED_STORED 's'
+
+
+#endif /* PG_ATTRIBUTE_D_H */
diff --git a/src/backend/catalog/pg_auth_members_d.h b/src/backend/catalog/pg_auth_members_d.h
new file mode 100644
index 0000000..5fb40c3
--- /dev/null
+++ b/src/backend/catalog/pg_auth_members_d.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_auth_members_d.h
+ * Macro definitions for pg_auth_members
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AUTH_MEMBERS_D_H
+#define PG_AUTH_MEMBERS_D_H
+
+#define AuthMemRelationId 1261
+#define AuthMemRelation_Rowtype_Id 2843
+
+#define Anum_pg_auth_members_roleid 1
+#define Anum_pg_auth_members_member 2
+#define Anum_pg_auth_members_grantor 3
+#define Anum_pg_auth_members_admin_option 4
+
+#define Natts_pg_auth_members 4
+
+
+#endif /* PG_AUTH_MEMBERS_D_H */
diff --git a/src/backend/catalog/pg_authid_d.h b/src/backend/catalog/pg_authid_d.h
new file mode 100644
index 0000000..e894479
--- /dev/null
+++ b/src/backend/catalog/pg_authid_d.h
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_authid_d.h
+ * Macro definitions for pg_authid
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_AUTHID_D_H
+#define PG_AUTHID_D_H
+
+#define AuthIdRelationId 1260
+#define AuthIdRelation_Rowtype_Id 2842
+
+#define Anum_pg_authid_oid 1
+#define Anum_pg_authid_rolname 2
+#define Anum_pg_authid_rolsuper 3
+#define Anum_pg_authid_rolinherit 4
+#define Anum_pg_authid_rolcreaterole 5
+#define Anum_pg_authid_rolcreatedb 6
+#define Anum_pg_authid_rolcanlogin 7
+#define Anum_pg_authid_rolreplication 8
+#define Anum_pg_authid_rolbypassrls 9
+#define Anum_pg_authid_rolconnlimit 10
+#define Anum_pg_authid_rolpassword 11
+#define Anum_pg_authid_rolvaliduntil 12
+
+#define Natts_pg_authid 12
+
+#define BOOTSTRAP_SUPERUSERID 10
+#define DEFAULT_ROLE_MONITOR 3373
+#define DEFAULT_ROLE_READ_ALL_SETTINGS 3374
+#define DEFAULT_ROLE_READ_ALL_STATS 3375
+#define DEFAULT_ROLE_STAT_SCAN_TABLES 3377
+#define DEFAULT_ROLE_READ_SERVER_FILES 4569
+#define DEFAULT_ROLE_WRITE_SERVER_FILES 4570
+#define DEFAULT_ROLE_EXECUTE_SERVER_PROGRAM 4571
+#define DEFAULT_ROLE_SIGNAL_BACKENDID 4200
+
+#endif /* PG_AUTHID_D_H */
diff --git a/src/backend/catalog/pg_cast.c b/src/backend/catalog/pg_cast.c
new file mode 100644
index 0000000..56aacd7
--- /dev/null
+++ b/src/backend/catalog/pg_cast.c
@@ -0,0 +1,123 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_cast.c
+ * routines to support manipulation of the pg_cast relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_cast.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_cast.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "utils/builtins.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+/*
+ * ----------------------------------------------------------------
+ * CastCreate
+ *
+ * Forms and inserts catalog tuples for a new cast being created.
+ * Caller must have already checked privileges, and done consistency
+ * checks on the given datatypes and cast function (if applicable).
+ *
+ * 'behavior' indicates the types of the dependencies that the new
+ * cast will have on its input and output types and the cast function.
+ * ----------------------------------------------------------------
+ */
+ObjectAddress
+CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, char castcontext,
+ char castmethod, DependencyType behavior)
+{
+ Relation relation;
+ HeapTuple tuple;
+ Oid castid;
+ Datum values[Natts_pg_cast];
+ bool nulls[Natts_pg_cast];
+ ObjectAddress myself,
+ referenced;
+
+ relation = table_open(CastRelationId, RowExclusiveLock);
+
+ /*
+ * Check for duplicate. This is just to give a friendly error message,
+ * the unique index would catch it anyway (so no need to sweat about race
+ * conditions).
+ */
+ tuple = SearchSysCache2(CASTSOURCETARGET,
+ ObjectIdGetDatum(sourcetypeid),
+ ObjectIdGetDatum(targettypeid));
+ if (HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("cast from type %s to type %s already exists",
+ format_type_be(sourcetypeid),
+ format_type_be(targettypeid))));
+
+ /* ready to go */
+ castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid);
+ values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid);
+ values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
+ values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
+ values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
+ values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
+ values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
+
+ MemSet(nulls, false, sizeof(nulls));
+
+ tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
+
+ CatalogTupleInsert(relation, tuple);
+
+ /* make dependency entries */
+ myself.classId = CastRelationId;
+ myself.objectId = castid;
+ myself.objectSubId = 0;
+
+ /* dependency on source type */
+ referenced.classId = TypeRelationId;
+ referenced.objectId = sourcetypeid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, behavior);
+
+ /* dependency on target type */
+ referenced.classId = TypeRelationId;
+ referenced.objectId = targettypeid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, behavior);
+
+ /* dependency on function */
+ if (OidIsValid(funcid))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = funcid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, behavior);
+ }
+
+ /* dependency on extension */
+ recordDependencyOnCurrentExtension(&myself, false);
+
+ /* Post creation hook for new cast */
+ InvokeObjectPostCreateHook(CastRelationId, castid, 0);
+
+ heap_freetuple(tuple);
+
+ table_close(relation, RowExclusiveLock);
+
+ return myself;
+}
diff --git a/src/backend/catalog/pg_cast_d.h b/src/backend/catalog/pg_cast_d.h
new file mode 100644
index 0000000..425aab7
--- /dev/null
+++ b/src/backend/catalog/pg_cast_d.h
@@ -0,0 +1,62 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_cast_d.h
+ * Macro definitions for pg_cast
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CAST_D_H
+#define PG_CAST_D_H
+
+#define CastRelationId 2605
+
+#define Anum_pg_cast_oid 1
+#define Anum_pg_cast_castsource 2
+#define Anum_pg_cast_casttarget 3
+#define Anum_pg_cast_castfunc 4
+#define Anum_pg_cast_castcontext 5
+#define Anum_pg_cast_castmethod 6
+
+#define Natts_pg_cast 6
+
+
+/*
+ * The allowable values for pg_cast.castcontext are specified by this enum.
+ * Since castcontext is stored as a "char", we use ASCII codes for human
+ * convenience in reading the table. Note that internally to the backend,
+ * these values are converted to the CoercionContext enum (see primnodes.h),
+ * which is defined to sort in a convenient order; the ASCII codes don't
+ * have to sort in any special order.
+ */
+
+typedef enum CoercionCodes
+{
+ COERCION_CODE_IMPLICIT = 'i', /* coercion in context of expression */
+ COERCION_CODE_ASSIGNMENT = 'a', /* coercion in context of assignment */
+ COERCION_CODE_EXPLICIT = 'e' /* explicit cast operation */
+} CoercionCodes;
+
+/*
+ * The allowable values for pg_cast.castmethod are specified by this enum.
+ * Since castmethod is stored as a "char", we use ASCII codes for human
+ * convenience in reading the table.
+ */
+typedef enum CoercionMethod
+{
+ COERCION_METHOD_FUNCTION = 'f', /* use a function */
+ COERCION_METHOD_BINARY = 'b', /* types are binary-compatible */
+ COERCION_METHOD_INOUT = 'i' /* use input/output functions */
+} CoercionMethod;
+
+
+#endif /* PG_CAST_D_H */
diff --git a/src/backend/catalog/pg_class_d.h b/src/backend/catalog/pg_class_d.h
new file mode 100644
index 0000000..7f9a66c
--- /dev/null
+++ b/src/backend/catalog/pg_class_d.h
@@ -0,0 +1,103 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_class_d.h
+ * Macro definitions for pg_class
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CLASS_D_H
+#define PG_CLASS_D_H
+
+#define RelationRelationId 1259
+#define RelationRelation_Rowtype_Id 83
+
+#define Anum_pg_class_oid 1
+#define Anum_pg_class_relname 2
+#define Anum_pg_class_relnamespace 3
+#define Anum_pg_class_reltype 4
+#define Anum_pg_class_reloftype 5
+#define Anum_pg_class_relowner 6
+#define Anum_pg_class_relam 7
+#define Anum_pg_class_relfilenode 8
+#define Anum_pg_class_reltablespace 9
+#define Anum_pg_class_relpages 10
+#define Anum_pg_class_reltuples 11
+#define Anum_pg_class_relallvisible 12
+#define Anum_pg_class_reltoastrelid 13
+#define Anum_pg_class_relhasindex 14
+#define Anum_pg_class_relisshared 15
+#define Anum_pg_class_relpersistence 16
+#define Anum_pg_class_relkind 17
+#define Anum_pg_class_relnatts 18
+#define Anum_pg_class_relchecks 19
+#define Anum_pg_class_relhasrules 20
+#define Anum_pg_class_relhastriggers 21
+#define Anum_pg_class_relhassubclass 22
+#define Anum_pg_class_relrowsecurity 23
+#define Anum_pg_class_relforcerowsecurity 24
+#define Anum_pg_class_relispopulated 25
+#define Anum_pg_class_relreplident 26
+#define Anum_pg_class_relispartition 27
+#define Anum_pg_class_relrewrite 28
+#define Anum_pg_class_relfrozenxid 29
+#define Anum_pg_class_relminmxid 30
+#define Anum_pg_class_relacl 31
+#define Anum_pg_class_reloptions 32
+#define Anum_pg_class_relpartbound 33
+
+#define Natts_pg_class 33
+
+
+#define RELKIND_RELATION 'r' /* ordinary table */
+#define RELKIND_INDEX 'i' /* secondary index */
+#define RELKIND_SEQUENCE 'S' /* sequence object */
+#define RELKIND_TOASTVALUE 't' /* for out-of-line values */
+#define RELKIND_VIEW 'v' /* view */
+#define RELKIND_MATVIEW 'm' /* materialized view */
+#define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
+#define RELKIND_FOREIGN_TABLE 'f' /* foreign table */
+#define RELKIND_PARTITIONED_TABLE 'p' /* partitioned table */
+#define RELKIND_PARTITIONED_INDEX 'I' /* partitioned index */
+
+#define RELPERSISTENCE_PERMANENT 'p' /* regular table */
+#define RELPERSISTENCE_UNLOGGED 'u' /* unlogged permanent table */
+#define RELPERSISTENCE_TEMP 't' /* temporary table */
+
+/* default selection for replica identity (primary key or nothing) */
+#define REPLICA_IDENTITY_DEFAULT 'd'
+/* no replica identity is logged for this relation */
+#define REPLICA_IDENTITY_NOTHING 'n'
+/* all columns are logged as replica identity */
+#define REPLICA_IDENTITY_FULL 'f'
+/*
+ * an explicitly chosen candidate key's columns are used as replica identity.
+ * Note this will still be set if the index has been dropped; in that case it
+ * has the same meaning as 'd'.
+ */
+#define REPLICA_IDENTITY_INDEX 'i'
+
+/*
+ * Relation kinds that have physical storage. These relations normally have
+ * relfilenode set to non-zero, but it can also be zero if the relation is
+ * mapped.
+ */
+#define RELKIND_HAS_STORAGE(relkind) \
+ ((relkind) == RELKIND_RELATION || \
+ (relkind) == RELKIND_INDEX || \
+ (relkind) == RELKIND_SEQUENCE || \
+ (relkind) == RELKIND_TOASTVALUE || \
+ (relkind) == RELKIND_MATVIEW)
+
+
+
+#endif /* PG_CLASS_D_H */
diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c
new file mode 100644
index 0000000..8559779
--- /dev/null
+++ b/src/backend/catalog/pg_collation.c
@@ -0,0 +1,241 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_collation.c
+ * routines to support manipulation of the pg_collation relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_collation.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/table.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_namespace.h"
+#include "mb/pg_wchar.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/pg_locale.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+
+/*
+ * CollationCreate
+ *
+ * Add a new tuple to pg_collation.
+ *
+ * if_not_exists: if true, don't fail on duplicate name, just print a notice
+ * and return InvalidOid.
+ * quiet: if true, don't fail on duplicate name, just silently return
+ * InvalidOid (overrides if_not_exists).
+ */
+Oid
+CollationCreate(const char *collname, Oid collnamespace,
+ Oid collowner,
+ char collprovider,
+ bool collisdeterministic,
+ int32 collencoding,
+ const char *collcollate, const char *collctype,
+ const char *collversion,
+ bool if_not_exists,
+ bool quiet)
+{
+ Relation rel;
+ TupleDesc tupDesc;
+ HeapTuple tup;
+ Datum values[Natts_pg_collation];
+ bool nulls[Natts_pg_collation];
+ NameData name_name,
+ name_collate,
+ name_ctype;
+ Oid oid;
+ ObjectAddress myself,
+ referenced;
+
+ AssertArg(collname);
+ AssertArg(collnamespace);
+ AssertArg(collowner);
+ AssertArg(collcollate);
+ AssertArg(collctype);
+
+ /*
+ * Make sure there is no existing collation of same name & encoding.
+ *
+ * This would be caught by the unique index anyway; we're just giving a
+ * friendlier error message. The unique index provides a backstop against
+ * race conditions.
+ */
+ if (SearchSysCacheExists3(COLLNAMEENCNSP,
+ PointerGetDatum(collname),
+ Int32GetDatum(collencoding),
+ ObjectIdGetDatum(collnamespace)))
+ {
+ if (quiet)
+ return InvalidOid;
+ else if (if_not_exists)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ collencoding == -1
+ ? errmsg("collation \"%s\" already exists, skipping",
+ collname)
+ : errmsg("collation \"%s\" for encoding \"%s\" already exists, skipping",
+ collname, pg_encoding_to_char(collencoding))));
+ return InvalidOid;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ collencoding == -1
+ ? errmsg("collation \"%s\" already exists",
+ collname)
+ : errmsg("collation \"%s\" for encoding \"%s\" already exists",
+ collname, pg_encoding_to_char(collencoding))));
+ }
+
+ /* open pg_collation; see below about the lock level */
+ rel = table_open(CollationRelationId, ShareRowExclusiveLock);
+
+ /*
+ * Also forbid a specific-encoding collation shadowing an any-encoding
+ * collation, or an any-encoding collation being shadowed (see
+ * get_collation_name()). This test is not backed up by the unique index,
+ * so we take a ShareRowExclusiveLock earlier, to protect against
+ * concurrent changes fooling this check.
+ */
+ if ((collencoding == -1 &&
+ SearchSysCacheExists3(COLLNAMEENCNSP,
+ PointerGetDatum(collname),
+ Int32GetDatum(GetDatabaseEncoding()),
+ ObjectIdGetDatum(collnamespace))) ||
+ (collencoding != -1 &&
+ SearchSysCacheExists3(COLLNAMEENCNSP,
+ PointerGetDatum(collname),
+ Int32GetDatum(-1),
+ ObjectIdGetDatum(collnamespace))))
+ {
+ if (quiet)
+ {
+ table_close(rel, NoLock);
+ return InvalidOid;
+ }
+ else if (if_not_exists)
+ {
+ table_close(rel, NoLock);
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("collation \"%s\" already exists, skipping",
+ collname)));
+ return InvalidOid;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("collation \"%s\" already exists",
+ collname)));
+ }
+
+ tupDesc = RelationGetDescr(rel);
+
+ /* form a tuple */
+ memset(nulls, 0, sizeof(nulls));
+
+ namestrcpy(&name_name, collname);
+ oid = GetNewOidWithIndex(rel, CollationOidIndexId,
+ Anum_pg_collation_oid);
+ values[Anum_pg_collation_oid - 1] = ObjectIdGetDatum(oid);
+ values[Anum_pg_collation_collname - 1] = NameGetDatum(&name_name);
+ values[Anum_pg_collation_collnamespace - 1] = ObjectIdGetDatum(collnamespace);
+ values[Anum_pg_collation_collowner - 1] = ObjectIdGetDatum(collowner);
+ values[Anum_pg_collation_collprovider - 1] = CharGetDatum(collprovider);
+ values[Anum_pg_collation_collisdeterministic - 1] = BoolGetDatum(collisdeterministic);
+ values[Anum_pg_collation_collencoding - 1] = Int32GetDatum(collencoding);
+ namestrcpy(&name_collate, collcollate);
+ values[Anum_pg_collation_collcollate - 1] = NameGetDatum(&name_collate);
+ namestrcpy(&name_ctype, collctype);
+ values[Anum_pg_collation_collctype - 1] = NameGetDatum(&name_ctype);
+ if (collversion)
+ values[Anum_pg_collation_collversion - 1] = CStringGetTextDatum(collversion);
+ else
+ nulls[Anum_pg_collation_collversion - 1] = true;
+
+ tup = heap_form_tuple(tupDesc, values, nulls);
+
+ /* insert a new tuple */
+ CatalogTupleInsert(rel, tup);
+ Assert(OidIsValid(oid));
+
+ /* set up dependencies for the new collation */
+ myself.classId = CollationRelationId;
+ myself.objectId = oid;
+ myself.objectSubId = 0;
+
+ /* create dependency on namespace */
+ referenced.classId = NamespaceRelationId;
+ referenced.objectId = collnamespace;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* create dependency on owner */
+ recordDependencyOnOwner(CollationRelationId, oid, collowner);
+
+ /* dependency on extension */
+ recordDependencyOnCurrentExtension(&myself, false);
+
+ /* Post creation hook for new collation */
+ InvokeObjectPostCreateHook(CollationRelationId, oid, 0);
+
+ heap_freetuple(tup);
+ table_close(rel, NoLock);
+
+ return oid;
+}
+
+/*
+ * RemoveCollationById
+ *
+ * Remove a tuple from pg_collation by Oid. This function is solely
+ * called inside catalog/dependency.c
+ */
+void
+RemoveCollationById(Oid collationOid)
+{
+ Relation rel;
+ ScanKeyData scanKeyData;
+ SysScanDesc scandesc;
+ HeapTuple tuple;
+
+ rel = table_open(CollationRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&scanKeyData,
+ Anum_pg_collation_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(collationOid));
+
+ scandesc = systable_beginscan(rel, CollationOidIndexId, true,
+ NULL, 1, &scanKeyData);
+
+ tuple = systable_getnext(scandesc);
+
+ if (HeapTupleIsValid(tuple))
+ CatalogTupleDelete(rel, &tuple->t_self);
+ else
+ elog(ERROR, "could not find tuple for collation %u", collationOid);
+
+ systable_endscan(scandesc);
+
+ table_close(rel, RowExclusiveLock);
+}
diff --git a/src/backend/catalog/pg_collation_d.h b/src/backend/catalog/pg_collation_d.h
new file mode 100644
index 0000000..e7545ff
--- /dev/null
+++ b/src/backend/catalog/pg_collation_d.h
@@ -0,0 +1,45 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_collation_d.h
+ * Macro definitions for pg_collation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_COLLATION_D_H
+#define PG_COLLATION_D_H
+
+#define CollationRelationId 3456
+
+#define Anum_pg_collation_oid 1
+#define Anum_pg_collation_collname 2
+#define Anum_pg_collation_collnamespace 3
+#define Anum_pg_collation_collowner 4
+#define Anum_pg_collation_collprovider 5
+#define Anum_pg_collation_collisdeterministic 6
+#define Anum_pg_collation_collencoding 7
+#define Anum_pg_collation_collcollate 8
+#define Anum_pg_collation_collctype 9
+#define Anum_pg_collation_collversion 10
+
+#define Natts_pg_collation 10
+
+
+#define COLLPROVIDER_DEFAULT 'd'
+#define COLLPROVIDER_ICU 'i'
+#define COLLPROVIDER_LIBC 'c'
+
+#define DEFAULT_COLLATION_OID 100
+#define C_COLLATION_OID 950
+#define POSIX_COLLATION_OID 951
+
+#endif /* PG_COLLATION_D_H */
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
new file mode 100644
index 0000000..90932be
--- /dev/null
+++ b/src/backend/catalog/pg_constraint.c
@@ -0,0 +1,1318 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_constraint.c
+ * routines to support manipulation of the pg_constraint relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_constraint.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/table.h"
+#include "access/xact.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_constraint.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_type.h"
+#include "commands/defrem.h"
+#include "commands/tablecmds.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+
+/*
+ * CreateConstraintEntry
+ * Create a constraint table entry.
+ *
+ * Subsidiary records (such as triggers or indexes to implement the
+ * constraint) are *not* created here. But we do make dependency links
+ * from the constraint to the things it depends on.
+ *
+ * The new constraint's OID is returned.
+ */
+Oid
+CreateConstraintEntry(const char *constraintName,
+ Oid constraintNamespace,
+ char constraintType,
+ bool isDeferrable,
+ bool isDeferred,
+ bool isValidated,
+ Oid parentConstrId,
+ Oid relId,
+ const int16 *constraintKey,
+ int constraintNKeys,
+ int constraintNTotalKeys,
+ Oid domainId,
+ Oid indexRelId,
+ Oid foreignRelId,
+ const int16 *foreignKey,
+ const Oid *pfEqOp,
+ const Oid *ppEqOp,
+ const Oid *ffEqOp,
+ int foreignNKeys,
+ char foreignUpdateType,
+ char foreignDeleteType,
+ char foreignMatchType,
+ const Oid *exclOp,
+ Node *conExpr,
+ const char *conBin,
+ bool conIsLocal,
+ int conInhCount,
+ bool conNoInherit,
+ bool is_internal)
+{
+ Relation conDesc;
+ Oid conOid;
+ HeapTuple tup;
+ bool nulls[Natts_pg_constraint];
+ Datum values[Natts_pg_constraint];
+ ArrayType *conkeyArray;
+ ArrayType *confkeyArray;
+ ArrayType *conpfeqopArray;
+ ArrayType *conppeqopArray;
+ ArrayType *conffeqopArray;
+ ArrayType *conexclopArray;
+ NameData cname;
+ int i;
+ ObjectAddress conobject;
+
+ conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
+
+ Assert(constraintName);
+ namestrcpy(&cname, constraintName);
+
+ /*
+ * Convert C arrays into Postgres arrays.
+ */
+ if (constraintNKeys > 0)
+ {
+ Datum *conkey;
+
+ conkey = (Datum *) palloc(constraintNKeys * sizeof(Datum));
+ for (i = 0; i < constraintNKeys; i++)
+ conkey[i] = Int16GetDatum(constraintKey[i]);
+ conkeyArray = construct_array(conkey, constraintNKeys,
+ INT2OID, 2, true, TYPALIGN_SHORT);
+ }
+ else
+ conkeyArray = NULL;
+
+ if (foreignNKeys > 0)
+ {
+ Datum *fkdatums;
+
+ fkdatums = (Datum *) palloc(foreignNKeys * sizeof(Datum));
+ for (i = 0; i < foreignNKeys; i++)
+ fkdatums[i] = Int16GetDatum(foreignKey[i]);
+ confkeyArray = construct_array(fkdatums, foreignNKeys,
+ INT2OID, 2, true, TYPALIGN_SHORT);
+ for (i = 0; i < foreignNKeys; i++)
+ fkdatums[i] = ObjectIdGetDatum(pfEqOp[i]);
+ conpfeqopArray = construct_array(fkdatums, foreignNKeys,
+ OIDOID, sizeof(Oid), true, TYPALIGN_INT);
+ for (i = 0; i < foreignNKeys; i++)
+ fkdatums[i] = ObjectIdGetDatum(ppEqOp[i]);
+ conppeqopArray = construct_array(fkdatums, foreignNKeys,
+ OIDOID, sizeof(Oid), true, TYPALIGN_INT);
+ for (i = 0; i < foreignNKeys; i++)
+ fkdatums[i] = ObjectIdGetDatum(ffEqOp[i]);
+ conffeqopArray = construct_array(fkdatums, foreignNKeys,
+ OIDOID, sizeof(Oid), true, TYPALIGN_INT);
+ }
+ else
+ {
+ confkeyArray = NULL;
+ conpfeqopArray = NULL;
+ conppeqopArray = NULL;
+ conffeqopArray = NULL;
+ }
+
+ if (exclOp != NULL)
+ {
+ Datum *opdatums;
+
+ opdatums = (Datum *) palloc(constraintNKeys * sizeof(Datum));
+ for (i = 0; i < constraintNKeys; i++)
+ opdatums[i] = ObjectIdGetDatum(exclOp[i]);
+ conexclopArray = construct_array(opdatums, constraintNKeys,
+ OIDOID, sizeof(Oid), true, TYPALIGN_INT);
+ }
+ else
+ conexclopArray = NULL;
+
+ /* initialize nulls and values */
+ for (i = 0; i < Natts_pg_constraint; i++)
+ {
+ nulls[i] = false;
+ values[i] = (Datum) NULL;
+ }
+
+ conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId,
+ Anum_pg_constraint_oid);
+ values[Anum_pg_constraint_oid - 1] = ObjectIdGetDatum(conOid);
+ values[Anum_pg_constraint_conname - 1] = NameGetDatum(&cname);
+ values[Anum_pg_constraint_connamespace - 1] = ObjectIdGetDatum(constraintNamespace);
+ values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType);
+ values[Anum_pg_constraint_condeferrable - 1] = BoolGetDatum(isDeferrable);
+ values[Anum_pg_constraint_condeferred - 1] = BoolGetDatum(isDeferred);
+ values[Anum_pg_constraint_convalidated - 1] = BoolGetDatum(isValidated);
+ values[Anum_pg_constraint_conrelid - 1] = ObjectIdGetDatum(relId);
+ values[Anum_pg_constraint_contypid - 1] = ObjectIdGetDatum(domainId);
+ values[Anum_pg_constraint_conindid - 1] = ObjectIdGetDatum(indexRelId);
+ values[Anum_pg_constraint_conparentid - 1] = ObjectIdGetDatum(parentConstrId);
+ values[Anum_pg_constraint_confrelid - 1] = ObjectIdGetDatum(foreignRelId);
+ values[Anum_pg_constraint_confupdtype - 1] = CharGetDatum(foreignUpdateType);
+ values[Anum_pg_constraint_confdeltype - 1] = CharGetDatum(foreignDeleteType);
+ values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType);
+ values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal);
+ values[Anum_pg_constraint_coninhcount - 1] = Int32GetDatum(conInhCount);
+ values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit);
+
+ if (conkeyArray)
+ values[Anum_pg_constraint_conkey - 1] = PointerGetDatum(conkeyArray);
+ else
+ nulls[Anum_pg_constraint_conkey - 1] = true;
+
+ if (confkeyArray)
+ values[Anum_pg_constraint_confkey - 1] = PointerGetDatum(confkeyArray);
+ else
+ nulls[Anum_pg_constraint_confkey - 1] = true;
+
+ if (conpfeqopArray)
+ values[Anum_pg_constraint_conpfeqop - 1] = PointerGetDatum(conpfeqopArray);
+ else
+ nulls[Anum_pg_constraint_conpfeqop - 1] = true;
+
+ if (conppeqopArray)
+ values[Anum_pg_constraint_conppeqop - 1] = PointerGetDatum(conppeqopArray);
+ else
+ nulls[Anum_pg_constraint_conppeqop - 1] = true;
+
+ if (conffeqopArray)
+ values[Anum_pg_constraint_conffeqop - 1] = PointerGetDatum(conffeqopArray);
+ else
+ nulls[Anum_pg_constraint_conffeqop - 1] = true;
+
+ if (conexclopArray)
+ values[Anum_pg_constraint_conexclop - 1] = PointerGetDatum(conexclopArray);
+ else
+ nulls[Anum_pg_constraint_conexclop - 1] = true;
+
+ if (conBin)
+ values[Anum_pg_constraint_conbin - 1] = CStringGetTextDatum(conBin);
+ else
+ nulls[Anum_pg_constraint_conbin - 1] = true;
+
+ tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls);
+
+ CatalogTupleInsert(conDesc, tup);
+
+ conobject.classId = ConstraintRelationId;
+ conobject.objectId = conOid;
+ conobject.objectSubId = 0;
+
+ table_close(conDesc, RowExclusiveLock);
+
+ if (OidIsValid(relId))
+ {
+ /*
+ * Register auto dependency from constraint to owning relation, or to
+ * specific column(s) if any are mentioned.
+ */
+ ObjectAddress relobject;
+
+ relobject.classId = RelationRelationId;
+ relobject.objectId = relId;
+ if (constraintNTotalKeys > 0)
+ {
+ for (i = 0; i < constraintNTotalKeys; i++)
+ {
+ relobject.objectSubId = constraintKey[i];
+
+ recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO);
+ }
+ }
+ else
+ {
+ relobject.objectSubId = 0;
+
+ recordDependencyOn(&conobject, &relobject, DEPENDENCY_AUTO);
+ }
+ }
+
+ if (OidIsValid(domainId))
+ {
+ /*
+ * Register auto dependency from constraint to owning domain
+ */
+ ObjectAddress domobject;
+
+ domobject.classId = TypeRelationId;
+ domobject.objectId = domainId;
+ domobject.objectSubId = 0;
+
+ recordDependencyOn(&conobject, &domobject, DEPENDENCY_AUTO);
+ }
+
+ if (OidIsValid(foreignRelId))
+ {
+ /*
+ * Register normal dependency from constraint to foreign relation, or
+ * to specific column(s) if any are mentioned.
+ */
+ ObjectAddress relobject;
+
+ relobject.classId = RelationRelationId;
+ relobject.objectId = foreignRelId;
+ if (foreignNKeys > 0)
+ {
+ for (i = 0; i < foreignNKeys; i++)
+ {
+ relobject.objectSubId = foreignKey[i];
+
+ recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
+ }
+ }
+ else
+ {
+ relobject.objectSubId = 0;
+
+ recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
+ }
+ }
+
+ if (OidIsValid(indexRelId) && constraintType == CONSTRAINT_FOREIGN)
+ {
+ /*
+ * Register normal dependency on the unique index that supports a
+ * foreign-key constraint. (Note: for indexes associated with unique
+ * or primary-key constraints, the dependency runs the other way, and
+ * is not made here.)
+ */
+ ObjectAddress relobject;
+
+ relobject.classId = RelationRelationId;
+ relobject.objectId = indexRelId;
+ relobject.objectSubId = 0;
+
+ recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
+ }
+
+ if (foreignNKeys > 0)
+ {
+ /*
+ * Register normal dependencies on the equality operators that support
+ * a foreign-key constraint. If the PK and FK types are the same then
+ * all three operators for a column are the same; otherwise they are
+ * different.
+ */
+ ObjectAddress oprobject;
+
+ oprobject.classId = OperatorRelationId;
+ oprobject.objectSubId = 0;
+
+ for (i = 0; i < foreignNKeys; i++)
+ {
+ oprobject.objectId = pfEqOp[i];
+ recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
+ if (ppEqOp[i] != pfEqOp[i])
+ {
+ oprobject.objectId = ppEqOp[i];
+ recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
+ }
+ if (ffEqOp[i] != pfEqOp[i])
+ {
+ oprobject.objectId = ffEqOp[i];
+ recordDependencyOn(&conobject, &oprobject, DEPENDENCY_NORMAL);
+ }
+ }
+ }
+
+ /*
+ * We don't bother to register dependencies on the exclusion operators of
+ * an exclusion constraint. We assume they are members of the opclass
+ * supporting the index, so there's an indirect dependency via that. (This
+ * would be pretty dicey for cross-type operators, but exclusion operators
+ * can never be cross-type.)
+ */
+
+ if (conExpr != NULL)
+ {
+ /*
+ * Register dependencies from constraint to objects mentioned in CHECK
+ * expression.
+ */
+ recordDependencyOnSingleRelExpr(&conobject, conExpr, relId,
+ DEPENDENCY_NORMAL,
+ DEPENDENCY_NORMAL, false);
+ }
+
+ /* Post creation hook for new constraint */
+ InvokeObjectPostCreateHookArg(ConstraintRelationId, conOid, 0,
+ is_internal);
+
+ return conOid;
+}
+
+/*
+ * Test whether given name is currently used as a constraint name
+ * for the given object (relation or domain).
+ *
+ * This is used to decide whether to accept a user-specified constraint name.
+ * It is deliberately not the same test as ChooseConstraintName uses to decide
+ * whether an auto-generated name is OK: here, we will allow it unless there
+ * is an identical constraint name in use *on the same object*.
+ *
+ * NB: Caller should hold exclusive lock on the given object, else
+ * this test can be fooled by concurrent additions.
+ */
+bool
+ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId,
+ const char *conname)
+{
+ bool found;
+ Relation conDesc;
+ SysScanDesc conscan;
+ ScanKeyData skey[3];
+
+ conDesc = table_open(ConstraintRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum((conCat == CONSTRAINT_RELATION)
+ ? objId : InvalidOid));
+ ScanKeyInit(&skey[1],
+ Anum_pg_constraint_contypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum((conCat == CONSTRAINT_DOMAIN)
+ ? objId : InvalidOid));
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(conname));
+
+ conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId,
+ true, NULL, 3, skey);
+
+ /* There can be at most one matching row */
+ found = (HeapTupleIsValid(systable_getnext(conscan)));
+
+ systable_endscan(conscan);
+ table_close(conDesc, AccessShareLock);
+
+ return found;
+}
+
+/*
+ * Does any constraint of the given name exist in the given namespace?
+ *
+ * This is used for code that wants to match ChooseConstraintName's rule
+ * that we should avoid autogenerating duplicate constraint names within a
+ * namespace.
+ */
+bool
+ConstraintNameExists(const char *conname, Oid namespaceid)
+{
+ bool found;
+ Relation conDesc;
+ SysScanDesc conscan;
+ ScanKeyData skey[2];
+
+ conDesc = table_open(ConstraintRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(conname));
+
+ ScanKeyInit(&skey[1],
+ Anum_pg_constraint_connamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(namespaceid));
+
+ conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
+ NULL, 2, skey);
+
+ found = (HeapTupleIsValid(systable_getnext(conscan)));
+
+ systable_endscan(conscan);
+ table_close(conDesc, AccessShareLock);
+
+ return found;
+}
+
+/*
+ * Select a nonconflicting name for a new constraint.
+ *
+ * The objective here is to choose a name that is unique within the
+ * specified namespace. Postgres does not require this, but the SQL
+ * spec does, and some apps depend on it. Therefore we avoid choosing
+ * default names that so conflict.
+ *
+ * name1, name2, and label are used the same way as for makeObjectName(),
+ * except that the label can't be NULL; digits will be appended to the label
+ * if needed to create a name that is unique within the specified namespace.
+ *
+ * 'others' can be a list of string names already chosen within the current
+ * command (but not yet reflected into the catalogs); we will not choose
+ * a duplicate of one of these either.
+ *
+ * Note: it is theoretically possible to get a collision anyway, if someone
+ * else chooses the same name concurrently. This is fairly unlikely to be
+ * a problem in practice, especially if one is holding an exclusive lock on
+ * the relation identified by name1.
+ *
+ * Returns a palloc'd string.
+ */
+char *
+ChooseConstraintName(const char *name1, const char *name2,
+ const char *label, Oid namespaceid,
+ List *others)
+{
+ int pass = 0;
+ char *conname = NULL;
+ char modlabel[NAMEDATALEN];
+ Relation conDesc;
+ SysScanDesc conscan;
+ ScanKeyData skey[2];
+ bool found;
+ ListCell *l;
+
+ conDesc = table_open(ConstraintRelationId, AccessShareLock);
+
+ /* try the unmodified label first */
+ StrNCpy(modlabel, label, sizeof(modlabel));
+
+ for (;;)
+ {
+ conname = makeObjectName(name1, name2, modlabel);
+
+ found = false;
+
+ foreach(l, others)
+ {
+ if (strcmp((char *) lfirst(l), conname) == 0)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(conname));
+
+ ScanKeyInit(&skey[1],
+ Anum_pg_constraint_connamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(namespaceid));
+
+ conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
+ NULL, 2, skey);
+
+ found = (HeapTupleIsValid(systable_getnext(conscan)));
+
+ systable_endscan(conscan);
+ }
+
+ if (!found)
+ break;
+
+ /* found a conflict, so try a new name component */
+ pfree(conname);
+ snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
+ }
+
+ table_close(conDesc, AccessShareLock);
+
+ return conname;
+}
+
+/*
+ * Delete a single constraint record.
+ */
+void
+RemoveConstraintById(Oid conId)
+{
+ Relation conDesc;
+ HeapTuple tup;
+ Form_pg_constraint con;
+
+ conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
+
+ tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conId));
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for constraint %u", conId);
+ con = (Form_pg_constraint) GETSTRUCT(tup);
+
+ /*
+ * Special processing depending on what the constraint is for.
+ */
+ if (OidIsValid(con->conrelid))
+ {
+ Relation rel;
+
+ /*
+ * If the constraint is for a relation, open and exclusive-lock the
+ * relation it's for.
+ */
+ rel = table_open(con->conrelid, AccessExclusiveLock);
+
+ /*
+ * We need to update the relchecks count if it is a check constraint
+ * being dropped. This update will force backends to rebuild relcache
+ * entries when we commit.
+ */
+ if (con->contype == CONSTRAINT_CHECK)
+ {
+ Relation pgrel;
+ HeapTuple relTup;
+ Form_pg_class classForm;
+
+ pgrel = table_open(RelationRelationId, RowExclusiveLock);
+ relTup = SearchSysCacheCopy1(RELOID,
+ ObjectIdGetDatum(con->conrelid));
+ if (!HeapTupleIsValid(relTup))
+ elog(ERROR, "cache lookup failed for relation %u",
+ con->conrelid);
+ classForm = (Form_pg_class) GETSTRUCT(relTup);
+
+ if (classForm->relchecks == 0) /* should not happen */
+ elog(ERROR, "relation \"%s\" has relchecks = 0",
+ RelationGetRelationName(rel));
+ classForm->relchecks--;
+
+ CatalogTupleUpdate(pgrel, &relTup->t_self, relTup);
+
+ heap_freetuple(relTup);
+
+ table_close(pgrel, RowExclusiveLock);
+ }
+
+ /* Keep lock on constraint's rel until end of xact */
+ table_close(rel, NoLock);
+ }
+ else if (OidIsValid(con->contypid))
+ {
+ /*
+ * XXX for now, do nothing special when dropping a domain constraint
+ *
+ * Probably there should be some form of locking on the domain type,
+ * but we have no such concept at the moment.
+ */
+ }
+ else
+ elog(ERROR, "constraint %u is not of a known type", conId);
+
+ /* Fry the constraint itself */
+ CatalogTupleDelete(conDesc, &tup->t_self);
+
+ /* Clean up */
+ ReleaseSysCache(tup);
+ table_close(conDesc, RowExclusiveLock);
+}
+
+/*
+ * RenameConstraintById
+ * Rename a constraint.
+ *
+ * Note: this isn't intended to be a user-exposed function; it doesn't check
+ * permissions etc. Currently this is only invoked when renaming an index
+ * that is associated with a constraint, but it's made a little more general
+ * than that with the expectation of someday having ALTER TABLE RENAME
+ * CONSTRAINT.
+ */
+void
+RenameConstraintById(Oid conId, const char *newname)
+{
+ Relation conDesc;
+ HeapTuple tuple;
+ Form_pg_constraint con;
+
+ conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCacheCopy1(CONSTROID, ObjectIdGetDatum(conId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for constraint %u", conId);
+ con = (Form_pg_constraint) GETSTRUCT(tuple);
+
+ /*
+ * For user-friendliness, check whether the name is already in use.
+ */
+ if (OidIsValid(con->conrelid) &&
+ ConstraintNameIsUsed(CONSTRAINT_RELATION,
+ con->conrelid,
+ newname))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("constraint \"%s\" for relation \"%s\" already exists",
+ newname, get_rel_name(con->conrelid))));
+ if (OidIsValid(con->contypid) &&
+ ConstraintNameIsUsed(CONSTRAINT_DOMAIN,
+ con->contypid,
+ newname))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("constraint \"%s\" for domain %s already exists",
+ newname, format_type_be(con->contypid))));
+
+ /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
+ namestrcpy(&(con->conname), newname);
+
+ CatalogTupleUpdate(conDesc, &tuple->t_self, tuple);
+
+ InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
+
+ heap_freetuple(tuple);
+ table_close(conDesc, RowExclusiveLock);
+}
+
+/*
+ * AlterConstraintNamespaces
+ * Find any constraints belonging to the specified object,
+ * and move them to the specified new namespace.
+ *
+ * isType indicates whether the owning object is a type or a relation.
+ */
+void
+AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
+ Oid newNspId, bool isType, ObjectAddresses *objsMoved)
+{
+ Relation conRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ conRel = table_open(ConstraintRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(isType ? InvalidOid : ownerId));
+ ScanKeyInit(&key[1],
+ Anum_pg_constraint_contypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(isType ? ownerId : InvalidOid));
+
+ scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid((tup = systable_getnext(scan))))
+ {
+ Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(tup);
+ ObjectAddress thisobj;
+
+ thisobj.classId = ConstraintRelationId;
+ thisobj.objectId = conform->oid;
+ thisobj.objectSubId = 0;
+
+ if (object_address_present(&thisobj, objsMoved))
+ continue;
+
+ /* Don't update if the object is already part of the namespace */
+ if (conform->connamespace == oldNspId && oldNspId != newNspId)
+ {
+ tup = heap_copytuple(tup);
+ conform = (Form_pg_constraint) GETSTRUCT(tup);
+
+ conform->connamespace = newNspId;
+
+ CatalogTupleUpdate(conRel, &tup->t_self, tup);
+
+ /*
+ * Note: currently, the constraint will not have its own
+ * dependency on the namespace, so we don't need to do
+ * changeDependencyFor().
+ */
+ }
+
+ InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
+
+ add_exact_object_address(&thisobj, objsMoved);
+ }
+
+ systable_endscan(scan);
+
+ table_close(conRel, RowExclusiveLock);
+}
+
+/*
+ * ConstraintSetParentConstraint
+ * Set a partition's constraint as child of its parent constraint,
+ * or remove the linkage if parentConstrId is InvalidOid.
+ *
+ * This updates the constraint's pg_constraint row to show it as inherited, and
+ * adds PARTITION dependencies to prevent the constraint from being deleted
+ * on its own. Alternatively, reverse that.
+ */
+void
+ConstraintSetParentConstraint(Oid childConstrId,
+ Oid parentConstrId,
+ Oid childTableId)
+{
+ Relation constrRel;
+ Form_pg_constraint constrForm;
+ HeapTuple tuple,
+ newtup;
+ ObjectAddress depender;
+ ObjectAddress referenced;
+
+ constrRel = table_open(ConstraintRelationId, RowExclusiveLock);
+ tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(childConstrId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for constraint %u", childConstrId);
+ newtup = heap_copytuple(tuple);
+ constrForm = (Form_pg_constraint) GETSTRUCT(newtup);
+ if (OidIsValid(parentConstrId))
+ {
+ /* don't allow setting parent for a constraint that already has one */
+ Assert(constrForm->coninhcount == 0);
+ if (constrForm->conparentid != InvalidOid)
+ elog(ERROR, "constraint %u already has a parent constraint",
+ childConstrId);
+
+ constrForm->conislocal = false;
+ constrForm->coninhcount++;
+ constrForm->conparentid = parentConstrId;
+
+ CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
+
+ ObjectAddressSet(depender, ConstraintRelationId, childConstrId);
+
+ ObjectAddressSet(referenced, ConstraintRelationId, parentConstrId);
+ recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
+
+ ObjectAddressSet(referenced, RelationRelationId, childTableId);
+ recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
+ }
+ else
+ {
+ constrForm->coninhcount--;
+ constrForm->conislocal = true;
+ constrForm->conparentid = InvalidOid;
+
+ /* Make sure there's no further inheritance. */
+ Assert(constrForm->coninhcount == 0);
+
+ CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);
+
+ deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
+ ConstraintRelationId,
+ DEPENDENCY_PARTITION_PRI);
+ deleteDependencyRecordsForClass(ConstraintRelationId, childConstrId,
+ RelationRelationId,
+ DEPENDENCY_PARTITION_SEC);
+ }
+
+ ReleaseSysCache(tuple);
+ table_close(constrRel, RowExclusiveLock);
+}
+
+
+/*
+ * get_relation_constraint_oid
+ * Find a constraint on the specified relation with the specified name.
+ * Returns constraint's OID.
+ */
+Oid
+get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok)
+{
+ Relation pg_constraint;
+ HeapTuple tuple;
+ SysScanDesc scan;
+ ScanKeyData skey[3];
+ Oid conOid = InvalidOid;
+
+ pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ ScanKeyInit(&skey[1],
+ Anum_pg_constraint_contypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(InvalidOid));
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(conname));
+
+ scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
+ NULL, 3, skey);
+
+ /* There can be at most one matching row */
+ if (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
+
+ systable_endscan(scan);
+
+ /* If no such constraint exists, complain */
+ if (!OidIsValid(conOid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("constraint \"%s\" for table \"%s\" does not exist",
+ conname, get_rel_name(relid))));
+
+ table_close(pg_constraint, AccessShareLock);
+
+ return conOid;
+}
+
+/*
+ * get_relation_constraint_attnos
+ * Find a constraint on the specified relation with the specified name
+ * and return the constrained columns.
+ *
+ * Returns a Bitmapset of the column attnos of the constrained columns, with
+ * attnos being offset by FirstLowInvalidHeapAttributeNumber so that system
+ * columns can be represented.
+ *
+ * *constraintOid is set to the OID of the constraint, or InvalidOid on
+ * failure.
+ */
+Bitmapset *
+get_relation_constraint_attnos(Oid relid, const char *conname,
+ bool missing_ok, Oid *constraintOid)
+{
+ Bitmapset *conattnos = NULL;
+ Relation pg_constraint;
+ HeapTuple tuple;
+ SysScanDesc scan;
+ ScanKeyData skey[3];
+
+ /* Set *constraintOid, to avoid complaints about uninitialized vars */
+ *constraintOid = InvalidOid;
+
+ pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ ScanKeyInit(&skey[1],
+ Anum_pg_constraint_contypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(InvalidOid));
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(conname));
+
+ scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
+ NULL, 3, skey);
+
+ /* There can be at most one matching row */
+ if (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ {
+ Datum adatum;
+ bool isNull;
+
+ *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
+
+ /* Extract the conkey array, ie, attnums of constrained columns */
+ adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
+ RelationGetDescr(pg_constraint), &isNull);
+ if (!isNull)
+ {
+ ArrayType *arr;
+ int numcols;
+ int16 *attnums;
+ int i;
+
+ arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
+ numcols = ARR_DIMS(arr)[0];
+ if (ARR_NDIM(arr) != 1 ||
+ numcols < 0 ||
+ ARR_HASNULL(arr) ||
+ ARR_ELEMTYPE(arr) != INT2OID)
+ elog(ERROR, "conkey is not a 1-D smallint array");
+ attnums = (int16 *) ARR_DATA_PTR(arr);
+
+ /* Construct the result value */
+ for (i = 0; i < numcols; i++)
+ {
+ conattnos = bms_add_member(conattnos,
+ attnums[i] - FirstLowInvalidHeapAttributeNumber);
+ }
+ }
+ }
+
+ systable_endscan(scan);
+
+ /* If no such constraint exists, complain */
+ if (!OidIsValid(*constraintOid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("constraint \"%s\" for table \"%s\" does not exist",
+ conname, get_rel_name(relid))));
+
+ table_close(pg_constraint, AccessShareLock);
+
+ return conattnos;
+}
+
+/*
+ * Return the OID of the constraint associated with the given index in the
+ * given relation; or InvalidOid if no such index is catalogued.
+ */
+Oid
+get_relation_idx_constraint_oid(Oid relationId, Oid indexId)
+{
+ Relation pg_constraint;
+ SysScanDesc scan;
+ ScanKeyData key;
+ HeapTuple tuple;
+ Oid constraintId = InvalidOid;
+
+ pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
+
+ ScanKeyInit(&key,
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(relationId));
+ scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId,
+ true, NULL, 1, &key);
+ while ((tuple = systable_getnext(scan)) != NULL)
+ {
+ Form_pg_constraint constrForm;
+
+ constrForm = (Form_pg_constraint) GETSTRUCT(tuple);
+ if (constrForm->conindid == indexId)
+ {
+ constraintId = constrForm->oid;
+ break;
+ }
+ }
+ systable_endscan(scan);
+
+ table_close(pg_constraint, AccessShareLock);
+ return constraintId;
+}
+
+/*
+ * get_domain_constraint_oid
+ * Find a constraint on the specified domain with the specified name.
+ * Returns constraint's OID.
+ */
+Oid
+get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok)
+{
+ Relation pg_constraint;
+ HeapTuple tuple;
+ SysScanDesc scan;
+ ScanKeyData skey[3];
+ Oid conOid = InvalidOid;
+
+ pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(InvalidOid));
+ ScanKeyInit(&skey[1],
+ Anum_pg_constraint_contypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(typid));
+ ScanKeyInit(&skey[2],
+ Anum_pg_constraint_conname,
+ BTEqualStrategyNumber, F_NAMEEQ,
+ CStringGetDatum(conname));
+
+ scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
+ NULL, 3, skey);
+
+ /* There can be at most one matching row */
+ if (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
+
+ systable_endscan(scan);
+
+ /* If no such constraint exists, complain */
+ if (!OidIsValid(conOid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("constraint \"%s\" for domain %s does not exist",
+ conname, format_type_be(typid))));
+
+ table_close(pg_constraint, AccessShareLock);
+
+ return conOid;
+}
+
+/*
+ * get_primary_key_attnos
+ * Identify the columns in a relation's primary key, if any.
+ *
+ * Returns a Bitmapset of the column attnos of the primary key's columns,
+ * with attnos being offset by FirstLowInvalidHeapAttributeNumber so that
+ * system columns can be represented.
+ *
+ * If there is no primary key, return NULL. We also return NULL if the pkey
+ * constraint is deferrable and deferrableOk is false.
+ *
+ * *constraintOid is set to the OID of the pkey constraint, or InvalidOid
+ * on failure.
+ */
+Bitmapset *
+get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
+{
+ Bitmapset *pkattnos = NULL;
+ Relation pg_constraint;
+ HeapTuple tuple;
+ SysScanDesc scan;
+ ScanKeyData skey[1];
+
+ /* Set *constraintOid, to avoid complaints about uninitialized vars */
+ *constraintOid = InvalidOid;
+
+ /* Scan pg_constraint for constraints of the target rel */
+ pg_constraint = table_open(ConstraintRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_constraint_conrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+
+ scan = systable_beginscan(pg_constraint, ConstraintRelidTypidNameIndexId, true,
+ NULL, 1, skey);
+
+ while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ {
+ Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
+ Datum adatum;
+ bool isNull;
+ ArrayType *arr;
+ int16 *attnums;
+ int numkeys;
+ int i;
+
+ /* Skip constraints that are not PRIMARY KEYs */
+ if (con->contype != CONSTRAINT_PRIMARY)
+ continue;
+
+ /*
+ * If the primary key is deferrable, but we've been instructed to
+ * ignore deferrable constraints, then we might as well give up
+ * searching, since there can only be a single primary key on a table.
+ */
+ if (con->condeferrable && !deferrableOk)
+ break;
+
+ /* Extract the conkey array, ie, attnums of PK's columns */
+ adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
+ RelationGetDescr(pg_constraint), &isNull);
+ if (isNull)
+ elog(ERROR, "null conkey for constraint %u",
+ ((Form_pg_constraint) GETSTRUCT(tuple))->oid);
+ arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
+ numkeys = ARR_DIMS(arr)[0];
+ if (ARR_NDIM(arr) != 1 ||
+ numkeys < 0 ||
+ ARR_HASNULL(arr) ||
+ ARR_ELEMTYPE(arr) != INT2OID)
+ elog(ERROR, "conkey is not a 1-D smallint array");
+ attnums = (int16 *) ARR_DATA_PTR(arr);
+
+ /* Construct the result value */
+ for (i = 0; i < numkeys; i++)
+ {
+ pkattnos = bms_add_member(pkattnos,
+ attnums[i] - FirstLowInvalidHeapAttributeNumber);
+ }
+ *constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
+
+ /* No need to search further */
+ break;
+ }
+
+ systable_endscan(scan);
+
+ table_close(pg_constraint, AccessShareLock);
+
+ return pkattnos;
+}
+
+/*
+ * Extract data from the pg_constraint tuple of a foreign-key constraint.
+ *
+ * All arguments save the first are output arguments; the last three of them
+ * can be passed as NULL if caller doesn't need them.
+ */
+void
+DeconstructFkConstraintRow(HeapTuple tuple, int *numfks,
+ AttrNumber *conkey, AttrNumber *confkey,
+ Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs)
+{
+ Oid constrId;
+ Datum adatum;
+ bool isNull;
+ ArrayType *arr;
+ int numkeys;
+
+ constrId = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
+
+ /*
+ * We expect the arrays to be 1-D arrays of the right types; verify that.
+ * We don't need to use deconstruct_array() since the array data is just
+ * going to look like a C array of values.
+ */
+ adatum = SysCacheGetAttr(CONSTROID, tuple,
+ Anum_pg_constraint_conkey, &isNull);
+ if (isNull)
+ elog(ERROR, "null conkey for constraint %u", constrId);
+ arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
+ if (ARR_NDIM(arr) != 1 ||
+ ARR_HASNULL(arr) ||
+ ARR_ELEMTYPE(arr) != INT2OID)
+ elog(ERROR, "conkey is not a 1-D smallint array");
+ numkeys = ARR_DIMS(arr)[0];
+ if (numkeys <= 0 || numkeys > INDEX_MAX_KEYS)
+ elog(ERROR, "foreign key constraint cannot have %d columns", numkeys);
+ memcpy(conkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
+ if ((Pointer) arr != DatumGetPointer(adatum))
+ pfree(arr); /* free de-toasted copy, if any */
+
+ adatum = SysCacheGetAttr(CONSTROID, tuple,
+ Anum_pg_constraint_confkey, &isNull);
+ if (isNull)
+ elog(ERROR, "null confkey for constraint %u", constrId);
+ arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
+ if (ARR_NDIM(arr) != 1 ||
+ ARR_DIMS(arr)[0] != numkeys ||
+ ARR_HASNULL(arr) ||
+ ARR_ELEMTYPE(arr) != INT2OID)
+ elog(ERROR, "confkey is not a 1-D smallint array");
+ memcpy(confkey, ARR_DATA_PTR(arr), numkeys * sizeof(int16));
+ if ((Pointer) arr != DatumGetPointer(adatum))
+ pfree(arr); /* free de-toasted copy, if any */
+
+ if (pf_eq_oprs)
+ {
+ adatum = SysCacheGetAttr(CONSTROID, tuple,
+ Anum_pg_constraint_conpfeqop, &isNull);
+ if (isNull)
+ elog(ERROR, "null conpfeqop for constraint %u", constrId);
+ arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
+ /* see TryReuseForeignKey if you change the test below */
+ if (ARR_NDIM(arr) != 1 ||
+ ARR_DIMS(arr)[0] != numkeys ||
+ ARR_HASNULL(arr) ||
+ ARR_ELEMTYPE(arr) != OIDOID)
+ elog(ERROR, "conpfeqop is not a 1-D Oid array");
+ memcpy(pf_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
+ if ((Pointer) arr != DatumGetPointer(adatum))
+ pfree(arr); /* free de-toasted copy, if any */
+ }
+
+ if (pp_eq_oprs)
+ {
+ adatum = SysCacheGetAttr(CONSTROID, tuple,
+ Anum_pg_constraint_conppeqop, &isNull);
+ if (isNull)
+ elog(ERROR, "null conppeqop for constraint %u", constrId);
+ arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
+ if (ARR_NDIM(arr) != 1 ||
+ ARR_DIMS(arr)[0] != numkeys ||
+ ARR_HASNULL(arr) ||
+ ARR_ELEMTYPE(arr) != OIDOID)
+ elog(ERROR, "conppeqop is not a 1-D Oid array");
+ memcpy(pp_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
+ if ((Pointer) arr != DatumGetPointer(adatum))
+ pfree(arr); /* free de-toasted copy, if any */
+ }
+
+ if (ff_eq_oprs)
+ {
+ adatum = SysCacheGetAttr(CONSTROID, tuple,
+ Anum_pg_constraint_conffeqop, &isNull);
+ if (isNull)
+ elog(ERROR, "null conffeqop for constraint %u", constrId);
+ arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
+ if (ARR_NDIM(arr) != 1 ||
+ ARR_DIMS(arr)[0] != numkeys ||
+ ARR_HASNULL(arr) ||
+ ARR_ELEMTYPE(arr) != OIDOID)
+ elog(ERROR, "conffeqop is not a 1-D Oid array");
+ memcpy(ff_eq_oprs, ARR_DATA_PTR(arr), numkeys * sizeof(Oid));
+ if ((Pointer) arr != DatumGetPointer(adatum))
+ pfree(arr); /* free de-toasted copy, if any */
+ }
+
+ *numfks = numkeys;
+}
+
+/*
+ * Determine whether a relation can be proven functionally dependent on
+ * a set of grouping columns. If so, return true and add the pg_constraint
+ * OIDs of the constraints needed for the proof to the *constraintDeps list.
+ *
+ * grouping_columns is a list of grouping expressions, in which columns of
+ * the rel of interest are Vars with the indicated varno/varlevelsup.
+ *
+ * Currently we only check to see if the rel has a primary key that is a
+ * subset of the grouping_columns. We could also use plain unique constraints
+ * if all their columns are known not null, but there's a problem: we need
+ * to be able to represent the not-null-ness as part of the constraints added
+ * to *constraintDeps. FIXME whenever not-null constraints get represented
+ * in pg_constraint.
+ */
+bool
+check_functional_grouping(Oid relid,
+ Index varno, Index varlevelsup,
+ List *grouping_columns,
+ List **constraintDeps)
+{
+ Bitmapset *pkattnos;
+ Bitmapset *groupbyattnos;
+ Oid constraintOid;
+ ListCell *gl;
+
+ /* If the rel has no PK, then we can't prove functional dependency */
+ pkattnos = get_primary_key_attnos(relid, false, &constraintOid);
+ if (pkattnos == NULL)
+ return false;
+
+ /* Identify all the rel's columns that appear in grouping_columns */
+ groupbyattnos = NULL;
+ foreach(gl, grouping_columns)
+ {
+ Var *gvar = (Var *) lfirst(gl);
+
+ if (IsA(gvar, Var) &&
+ gvar->varno == varno &&
+ gvar->varlevelsup == varlevelsup)
+ groupbyattnos = bms_add_member(groupbyattnos,
+ gvar->varattno - FirstLowInvalidHeapAttributeNumber);
+ }
+
+ if (bms_is_subset(pkattnos, groupbyattnos))
+ {
+ /* The PK is a subset of grouping_columns, so we win */
+ *constraintDeps = lappend_oid(*constraintDeps, constraintOid);
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/backend/catalog/pg_constraint_d.h b/src/backend/catalog/pg_constraint_d.h
new file mode 100644
index 0000000..3d98c62
--- /dev/null
+++ b/src/backend/catalog/pg_constraint_d.h
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_constraint_d.h
+ * Macro definitions for pg_constraint
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CONSTRAINT_D_H
+#define PG_CONSTRAINT_D_H
+
+#define ConstraintRelationId 2606
+
+#define Anum_pg_constraint_oid 1
+#define Anum_pg_constraint_conname 2
+#define Anum_pg_constraint_connamespace 3
+#define Anum_pg_constraint_contype 4
+#define Anum_pg_constraint_condeferrable 5
+#define Anum_pg_constraint_condeferred 6
+#define Anum_pg_constraint_convalidated 7
+#define Anum_pg_constraint_conrelid 8
+#define Anum_pg_constraint_contypid 9
+#define Anum_pg_constraint_conindid 10
+#define Anum_pg_constraint_conparentid 11
+#define Anum_pg_constraint_confrelid 12
+#define Anum_pg_constraint_confupdtype 13
+#define Anum_pg_constraint_confdeltype 14
+#define Anum_pg_constraint_confmatchtype 15
+#define Anum_pg_constraint_conislocal 16
+#define Anum_pg_constraint_coninhcount 17
+#define Anum_pg_constraint_connoinherit 18
+#define Anum_pg_constraint_conkey 19
+#define Anum_pg_constraint_confkey 20
+#define Anum_pg_constraint_conpfeqop 21
+#define Anum_pg_constraint_conppeqop 22
+#define Anum_pg_constraint_conffeqop 23
+#define Anum_pg_constraint_conexclop 24
+#define Anum_pg_constraint_conbin 25
+
+#define Natts_pg_constraint 25
+
+
+/* Valid values for contype */
+#define CONSTRAINT_CHECK 'c'
+#define CONSTRAINT_FOREIGN 'f'
+#define CONSTRAINT_PRIMARY 'p'
+#define CONSTRAINT_UNIQUE 'u'
+#define CONSTRAINT_TRIGGER 't'
+#define CONSTRAINT_EXCLUSION 'x'
+
+/*
+ * Valid values for confupdtype and confdeltype are the FKCONSTR_ACTION_xxx
+ * constants defined in parsenodes.h. Valid values for confmatchtype are
+ * the FKCONSTR_MATCH_xxx constants defined in parsenodes.h.
+ */
+
+
+#endif /* PG_CONSTRAINT_D_H */
diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c
new file mode 100644
index 0000000..b38df4f
--- /dev/null
+++ b/src/backend/catalog/pg_conversion.c
@@ -0,0 +1,213 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_conversion.c
+ * routines to support manipulation of the pg_conversion relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_conversion.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/tableam.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_conversion.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
+#include "mb/pg_wchar.h"
+#include "utils/builtins.h"
+#include "utils/catcache.h"
+#include "utils/fmgroids.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+/*
+ * ConversionCreate
+ *
+ * Add a new tuple to pg_conversion.
+ */
+ObjectAddress
+ConversionCreate(const char *conname, Oid connamespace,
+ Oid conowner,
+ int32 conforencoding, int32 contoencoding,
+ Oid conproc, bool def)
+{
+ int i;
+ Relation rel;
+ TupleDesc tupDesc;
+ HeapTuple tup;
+ Oid oid;
+ bool nulls[Natts_pg_conversion];
+ Datum values[Natts_pg_conversion];
+ NameData cname;
+ ObjectAddress myself,
+ referenced;
+
+ /* sanity checks */
+ if (!conname)
+ elog(ERROR, "no conversion name supplied");
+
+ /* make sure there is no existing conversion of same name */
+ if (SearchSysCacheExists2(CONNAMENSP,
+ PointerGetDatum(conname),
+ ObjectIdGetDatum(connamespace)))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("conversion \"%s\" already exists", conname)));
+
+ if (def)
+ {
+ /*
+ * make sure there is no existing default <for encoding><to encoding>
+ * pair in this name space
+ */
+ if (FindDefaultConversion(connamespace,
+ conforencoding,
+ contoencoding))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("default conversion for %s to %s already exists",
+ pg_encoding_to_char(conforencoding),
+ pg_encoding_to_char(contoencoding))));
+ }
+
+ /* open pg_conversion */
+ rel = table_open(ConversionRelationId, RowExclusiveLock);
+ tupDesc = rel->rd_att;
+
+ /* initialize nulls and values */
+ for (i = 0; i < Natts_pg_conversion; i++)
+ {
+ nulls[i] = false;
+ values[i] = (Datum) NULL;
+ }
+
+ /* form a tuple */
+ namestrcpy(&cname, conname);
+ oid = GetNewOidWithIndex(rel, ConversionOidIndexId,
+ Anum_pg_conversion_oid);
+ values[Anum_pg_conversion_oid - 1] = ObjectIdGetDatum(oid);
+ values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname);
+ values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace);
+ values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
+ values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
+ values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
+ values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
+ values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
+
+ tup = heap_form_tuple(tupDesc, values, nulls);
+
+ /* insert a new tuple */
+ CatalogTupleInsert(rel, tup);
+
+ myself.classId = ConversionRelationId;
+ myself.objectId = oid;
+ myself.objectSubId = 0;
+
+ /* create dependency on conversion procedure */
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = conproc;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* create dependency on namespace */
+ referenced.classId = NamespaceRelationId;
+ referenced.objectId = connamespace;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* create dependency on owner */
+ recordDependencyOnOwner(ConversionRelationId, oid, conowner);
+
+ /* dependency on extension */
+ recordDependencyOnCurrentExtension(&myself, false);
+
+ /* Post creation hook for new conversion */
+ InvokeObjectPostCreateHook(ConversionRelationId, oid, 0);
+
+ heap_freetuple(tup);
+ table_close(rel, RowExclusiveLock);
+
+ return myself;
+}
+
+/*
+ * RemoveConversionById
+ *
+ * Remove a tuple from pg_conversion by Oid. This function is solely
+ * called inside catalog/dependency.c
+ */
+void
+RemoveConversionById(Oid conversionOid)
+{
+ Relation rel;
+ HeapTuple tuple;
+ TableScanDesc scan;
+ ScanKeyData scanKeyData;
+
+ ScanKeyInit(&scanKeyData,
+ Anum_pg_conversion_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(conversionOid));
+
+ /* open pg_conversion */
+ rel = table_open(ConversionRelationId, RowExclusiveLock);
+
+ scan = table_beginscan_catalog(rel, 1, &scanKeyData);
+
+ /* search for the target tuple */
+ if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
+ CatalogTupleDelete(rel, &tuple->t_self);
+ else
+ elog(ERROR, "could not find tuple for conversion %u", conversionOid);
+ table_endscan(scan);
+ table_close(rel, RowExclusiveLock);
+}
+
+/*
+ * FindDefaultConversion
+ *
+ * Find "default" conversion proc by for_encoding and to_encoding in the
+ * given namespace.
+ *
+ * If found, returns the procedure's oid, otherwise InvalidOid. Note that
+ * you get the procedure's OID not the conversion's OID!
+ */
+Oid
+FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
+{
+ CatCList *catlist;
+ HeapTuple tuple;
+ Form_pg_conversion body;
+ Oid proc = InvalidOid;
+ int i;
+
+ catlist = SearchSysCacheList3(CONDEFAULT,
+ ObjectIdGetDatum(name_space),
+ Int32GetDatum(for_encoding),
+ Int32GetDatum(to_encoding));
+
+ for (i = 0; i < catlist->n_members; i++)
+ {
+ tuple = &catlist->members[i]->tuple;
+ body = (Form_pg_conversion) GETSTRUCT(tuple);
+ if (body->condefault)
+ {
+ proc = body->conproc;
+ break;
+ }
+ }
+ ReleaseSysCacheList(catlist);
+ return proc;
+}
diff --git a/src/backend/catalog/pg_conversion_d.h b/src/backend/catalog/pg_conversion_d.h
new file mode 100644
index 0000000..c991871
--- /dev/null
+++ b/src/backend/catalog/pg_conversion_d.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_conversion_d.h
+ * Macro definitions for pg_conversion
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CONVERSION_D_H
+#define PG_CONVERSION_D_H
+
+#define ConversionRelationId 2607
+
+#define Anum_pg_conversion_oid 1
+#define Anum_pg_conversion_conname 2
+#define Anum_pg_conversion_connamespace 3
+#define Anum_pg_conversion_conowner 4
+#define Anum_pg_conversion_conforencoding 5
+#define Anum_pg_conversion_contoencoding 6
+#define Anum_pg_conversion_conproc 7
+#define Anum_pg_conversion_condefault 8
+
+#define Natts_pg_conversion 8
+
+
+#endif /* PG_CONVERSION_D_H */
diff --git a/src/backend/catalog/pg_database_d.h b/src/backend/catalog/pg_database_d.h
new file mode 100644
index 0000000..7335d03
--- /dev/null
+++ b/src/backend/catalog/pg_database_d.h
@@ -0,0 +1,43 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_database_d.h
+ * Macro definitions for pg_database
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DATABASE_D_H
+#define PG_DATABASE_D_H
+
+#define DatabaseRelationId 1262
+#define DatabaseRelation_Rowtype_Id 1248
+
+#define Anum_pg_database_oid 1
+#define Anum_pg_database_datname 2
+#define Anum_pg_database_datdba 3
+#define Anum_pg_database_encoding 4
+#define Anum_pg_database_datcollate 5
+#define Anum_pg_database_datctype 6
+#define Anum_pg_database_datistemplate 7
+#define Anum_pg_database_datallowconn 8
+#define Anum_pg_database_datconnlimit 9
+#define Anum_pg_database_datlastsysoid 10
+#define Anum_pg_database_datfrozenxid 11
+#define Anum_pg_database_datminmxid 12
+#define Anum_pg_database_dattablespace 13
+#define Anum_pg_database_datacl 14
+
+#define Natts_pg_database 14
+
+#define TemplateDbOid 1
+
+#endif /* PG_DATABASE_D_H */
diff --git a/src/backend/catalog/pg_db_role_setting.c b/src/backend/catalog/pg_db_role_setting.c
new file mode 100644
index 0000000..33fc53a
--- /dev/null
+++ b/src/backend/catalog/pg_db_role_setting.c
@@ -0,0 +1,261 @@
+/*
+ * pg_db_role_setting.c
+ * Routines to support manipulation of the pg_db_role_setting relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_db_role_setting.c
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/tableam.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_db_role_setting.h"
+#include "utils/fmgroids.h"
+#include "utils/rel.h"
+
+void
+AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
+{
+ char *valuestr;
+ HeapTuple tuple;
+ Relation rel;
+ ScanKeyData scankey[2];
+ SysScanDesc scan;
+
+ valuestr = ExtractSetVariableArgs(setstmt);
+
+ /* Get the old tuple, if any. */
+
+ rel = table_open(DbRoleSettingRelationId, RowExclusiveLock);
+ ScanKeyInit(&scankey[0],
+ Anum_pg_db_role_setting_setdatabase,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(databaseid));
+ ScanKeyInit(&scankey[1],
+ Anum_pg_db_role_setting_setrole,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(roleid));
+ scan = systable_beginscan(rel, DbRoleSettingDatidRolidIndexId, true,
+ NULL, 2, scankey);
+ tuple = systable_getnext(scan);
+
+ /*
+ * There are three cases:
+ *
+ * - in RESET ALL, request GUC to reset the settings array and update the
+ * catalog if there's anything left, delete it otherwise
+ *
+ * - in other commands, if there's a tuple in pg_db_role_setting, update
+ * it; if it ends up empty, delete it
+ *
+ * - otherwise, insert a new pg_db_role_setting tuple, but only if the
+ * command is not RESET
+ */
+ if (setstmt->kind == VAR_RESET_ALL)
+ {
+ if (HeapTupleIsValid(tuple))
+ {
+ ArrayType *new = NULL;
+ Datum datum;
+ bool isnull;
+
+ datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
+ RelationGetDescr(rel), &isnull);
+
+ if (!isnull)
+ new = GUCArrayReset(DatumGetArrayTypeP(datum));
+
+ if (new)
+ {
+ Datum repl_val[Natts_pg_db_role_setting];
+ bool repl_null[Natts_pg_db_role_setting];
+ bool repl_repl[Natts_pg_db_role_setting];
+ HeapTuple newtuple;
+
+ memset(repl_repl, false, sizeof(repl_repl));
+
+ repl_val[Anum_pg_db_role_setting_setconfig - 1] =
+ PointerGetDatum(new);
+ repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
+ repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
+ repl_val, repl_null, repl_repl);
+ CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
+ }
+ else
+ CatalogTupleDelete(rel, &tuple->t_self);
+ }
+ }
+ else if (HeapTupleIsValid(tuple))
+ {
+ Datum repl_val[Natts_pg_db_role_setting];
+ bool repl_null[Natts_pg_db_role_setting];
+ bool repl_repl[Natts_pg_db_role_setting];
+ HeapTuple newtuple;
+ Datum datum;
+ bool isnull;
+ ArrayType *a;
+
+ memset(repl_repl, false, sizeof(repl_repl));
+ repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
+ repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
+
+ /* Extract old value of setconfig */
+ datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
+ RelationGetDescr(rel), &isnull);
+ a = isnull ? NULL : DatumGetArrayTypeP(datum);
+
+ /* Update (valuestr is NULL in RESET cases) */
+ if (valuestr)
+ a = GUCArrayAdd(a, setstmt->name, valuestr);
+ else
+ a = GUCArrayDelete(a, setstmt->name);
+
+ if (a)
+ {
+ repl_val[Anum_pg_db_role_setting_setconfig - 1] =
+ PointerGetDatum(a);
+
+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
+ repl_val, repl_null, repl_repl);
+ CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
+ }
+ else
+ CatalogTupleDelete(rel, &tuple->t_self);
+ }
+ else if (valuestr)
+ {
+ /* non-null valuestr means it's not RESET, so insert a new tuple */
+ HeapTuple newtuple;
+ Datum values[Natts_pg_db_role_setting];
+ bool nulls[Natts_pg_db_role_setting];
+ ArrayType *a;
+
+ memset(nulls, false, sizeof(nulls));
+
+ a = GUCArrayAdd(NULL, setstmt->name, valuestr);
+
+ values[Anum_pg_db_role_setting_setdatabase - 1] =
+ ObjectIdGetDatum(databaseid);
+ values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid);
+ values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a);
+ newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+
+ CatalogTupleInsert(rel, newtuple);
+ }
+
+ InvokeObjectPostAlterHookArg(DbRoleSettingRelationId,
+ databaseid, 0, roleid, false);
+
+ systable_endscan(scan);
+
+ /* Close pg_db_role_setting, but keep lock till commit */
+ table_close(rel, NoLock);
+}
+
+/*
+ * Drop some settings from the catalog. These can be for a particular
+ * database, or for a particular role. (It is of course possible to do both
+ * too, but it doesn't make sense for current uses.)
+ */
+void
+DropSetting(Oid databaseid, Oid roleid)
+{
+ Relation relsetting;
+ TableScanDesc scan;
+ ScanKeyData keys[2];
+ HeapTuple tup;
+ int numkeys = 0;
+
+ relsetting = table_open(DbRoleSettingRelationId, RowExclusiveLock);
+
+ if (OidIsValid(databaseid))
+ {
+ ScanKeyInit(&keys[numkeys],
+ Anum_pg_db_role_setting_setdatabase,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(databaseid));
+ numkeys++;
+ }
+ if (OidIsValid(roleid))
+ {
+ ScanKeyInit(&keys[numkeys],
+ Anum_pg_db_role_setting_setrole,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(roleid));
+ numkeys++;
+ }
+
+ scan = table_beginscan_catalog(relsetting, numkeys, keys);
+ while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
+ {
+ CatalogTupleDelete(relsetting, &tup->t_self);
+ }
+ table_endscan(scan);
+
+ table_close(relsetting, RowExclusiveLock);
+}
+
+/*
+ * Scan pg_db_role_setting looking for applicable settings, and load them on
+ * the current process.
+ *
+ * relsetting is pg_db_role_setting, already opened and locked.
+ *
+ * Note: we only consider setting for the exact databaseid/roleid combination.
+ * This probably needs to be called more than once, with InvalidOid passed as
+ * databaseid/roleid.
+ */
+void
+ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid,
+ Relation relsetting, GucSource source)
+{
+ SysScanDesc scan;
+ ScanKeyData keys[2];
+ HeapTuple tup;
+
+ ScanKeyInit(&keys[0],
+ Anum_pg_db_role_setting_setdatabase,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(databaseid));
+ ScanKeyInit(&keys[1],
+ Anum_pg_db_role_setting_setrole,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(roleid));
+
+ scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
+ snapshot, 2, keys);
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ bool isnull;
+ Datum datum;
+
+ datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
+ RelationGetDescr(relsetting), &isnull);
+ if (!isnull)
+ {
+ ArrayType *a = DatumGetArrayTypeP(datum);
+
+ /*
+ * We process all the options at SUSET level. We assume that the
+ * right to insert an option into pg_db_role_setting was checked
+ * when it was inserted.
+ */
+ ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
+ }
+ }
+
+ systable_endscan(scan);
+}
diff --git a/src/backend/catalog/pg_db_role_setting_d.h b/src/backend/catalog/pg_db_role_setting_d.h
new file mode 100644
index 0000000..b1414de
--- /dev/null
+++ b/src/backend/catalog/pg_db_role_setting_d.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_db_role_setting_d.h
+ * Macro definitions for pg_db_role_setting
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DB_ROLE_SETTING_D_H
+#define PG_DB_ROLE_SETTING_D_H
+
+#define DbRoleSettingRelationId 2964
+
+#define Anum_pg_db_role_setting_setdatabase 1
+#define Anum_pg_db_role_setting_setrole 2
+#define Anum_pg_db_role_setting_setconfig 3
+
+#define Natts_pg_db_role_setting 3
+
+
+#endif /* PG_DB_ROLE_SETTING_D_H */
diff --git a/src/backend/catalog/pg_default_acl_d.h b/src/backend/catalog/pg_default_acl_d.h
new file mode 100644
index 0000000..0ba9892
--- /dev/null
+++ b/src/backend/catalog/pg_default_acl_d.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_default_acl_d.h
+ * Macro definitions for pg_default_acl
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DEFAULT_ACL_D_H
+#define PG_DEFAULT_ACL_D_H
+
+#define DefaultAclRelationId 826
+
+#define Anum_pg_default_acl_oid 1
+#define Anum_pg_default_acl_defaclrole 2
+#define Anum_pg_default_acl_defaclnamespace 3
+#define Anum_pg_default_acl_defaclobjtype 4
+#define Anum_pg_default_acl_defaclacl 5
+
+#define Natts_pg_default_acl 5
+
+
+/*
+ * Types of objects for which the user is allowed to specify default
+ * permissions through pg_default_acl. These codes are used in the
+ * defaclobjtype column.
+ */
+#define DEFACLOBJ_RELATION 'r' /* table, view */
+#define DEFACLOBJ_SEQUENCE 'S' /* sequence */
+#define DEFACLOBJ_FUNCTION 'f' /* function */
+#define DEFACLOBJ_TYPE 'T' /* type */
+#define DEFACLOBJ_NAMESPACE 'n' /* namespace */
+
+
+#endif /* PG_DEFAULT_ACL_D_H */
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
new file mode 100644
index 0000000..21cfdca
--- /dev/null
+++ b/src/backend/catalog/pg_depend.c
@@ -0,0 +1,1068 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_depend.c
+ * routines to support manipulation of the pg_depend relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_depend.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_constraint.h"
+#include "catalog/pg_depend.h"
+#include "catalog/pg_extension.h"
+#include "commands/extension.h"
+#include "miscadmin.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+
+
+static bool isObjectPinned(const ObjectAddress *object, Relation rel);
+
+
+/*
+ * Record a dependency between 2 objects via their respective objectAddress.
+ * The first argument is the dependent object, the second the one it
+ * references.
+ *
+ * This simply creates an entry in pg_depend, without any other processing.
+ */
+void
+recordDependencyOn(const ObjectAddress *depender,
+ const ObjectAddress *referenced,
+ DependencyType behavior)
+{
+ recordMultipleDependencies(depender, referenced, 1, behavior);
+}
+
+/*
+ * Record multiple dependencies (of the same kind) for a single dependent
+ * object. This has a little less overhead than recording each separately.
+ */
+void
+recordMultipleDependencies(const ObjectAddress *depender,
+ const ObjectAddress *referenced,
+ int nreferenced,
+ DependencyType behavior)
+{
+ Relation dependDesc;
+ CatalogIndexState indstate;
+ HeapTuple tup;
+ int i;
+ bool nulls[Natts_pg_depend];
+ Datum values[Natts_pg_depend];
+
+ if (nreferenced <= 0)
+ return; /* nothing to do */
+
+ /*
+ * During bootstrap, do nothing since pg_depend may not exist yet. initdb
+ * will fill in appropriate pg_depend entries after bootstrap.
+ */
+ if (IsBootstrapProcessingMode())
+ return;
+
+ dependDesc = table_open(DependRelationId, RowExclusiveLock);
+
+ /* Don't open indexes unless we need to make an update */
+ indstate = NULL;
+
+ memset(nulls, false, sizeof(nulls));
+
+ for (i = 0; i < nreferenced; i++, referenced++)
+ {
+ /*
+ * If the referenced object is pinned by the system, there's no real
+ * need to record dependencies on it. This saves lots of space in
+ * pg_depend, so it's worth the time taken to check.
+ */
+ if (!isObjectPinned(referenced, dependDesc))
+ {
+ /*
+ * Record the Dependency. Note we don't bother to check for
+ * duplicate dependencies; there's no harm in them.
+ */
+ values[Anum_pg_depend_classid - 1] = ObjectIdGetDatum(depender->classId);
+ values[Anum_pg_depend_objid - 1] = ObjectIdGetDatum(depender->objectId);
+ values[Anum_pg_depend_objsubid - 1] = Int32GetDatum(depender->objectSubId);
+
+ values[Anum_pg_depend_refclassid - 1] = ObjectIdGetDatum(referenced->classId);
+ values[Anum_pg_depend_refobjid - 1] = ObjectIdGetDatum(referenced->objectId);
+ values[Anum_pg_depend_refobjsubid - 1] = Int32GetDatum(referenced->objectSubId);
+
+ values[Anum_pg_depend_deptype - 1] = CharGetDatum((char) behavior);
+
+ tup = heap_form_tuple(dependDesc->rd_att, values, nulls);
+
+ /* fetch index info only when we know we need it */
+ if (indstate == NULL)
+ indstate = CatalogOpenIndexes(dependDesc);
+
+ CatalogTupleInsertWithInfo(dependDesc, tup, indstate);
+
+ heap_freetuple(tup);
+ }
+ }
+
+ if (indstate != NULL)
+ CatalogCloseIndexes(indstate);
+
+ table_close(dependDesc, RowExclusiveLock);
+}
+
+/*
+ * If we are executing a CREATE EXTENSION operation, mark the given object
+ * as being a member of the extension. Otherwise, do nothing.
+ *
+ * This must be called during creation of any user-definable object type
+ * that could be a member of an extension.
+ *
+ * If isReplace is true, the object already existed (or might have already
+ * existed), so we must check for a pre-existing extension membership entry.
+ * Passing false is a guarantee that the object is newly created, and so
+ * could not already be a member of any extension.
+ */
+void
+recordDependencyOnCurrentExtension(const ObjectAddress *object,
+ bool isReplace)
+{
+ /* Only whole objects can be extension members */
+ Assert(object->objectSubId == 0);
+
+ if (creating_extension)
+ {
+ ObjectAddress extension;
+
+ /* Only need to check for existing membership if isReplace */
+ if (isReplace)
+ {
+ Oid oldext;
+
+ oldext = getExtensionOfObject(object->classId, object->objectId);
+ if (OidIsValid(oldext))
+ {
+ /* If already a member of this extension, nothing to do */
+ if (oldext == CurrentExtensionObject)
+ return;
+ /* Already a member of some other extension, so reject */
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("%s is already a member of extension \"%s\"",
+ getObjectDescription(object),
+ get_extension_name(oldext))));
+ }
+ }
+
+ /* OK, record it as a member of CurrentExtensionObject */
+ extension.classId = ExtensionRelationId;
+ extension.objectId = CurrentExtensionObject;
+ extension.objectSubId = 0;
+
+ recordDependencyOn(object, &extension, DEPENDENCY_EXTENSION);
+ }
+}
+
+/*
+ * deleteDependencyRecordsFor -- delete all records with given depender
+ * classId/objectId. Returns the number of records deleted.
+ *
+ * This is used when redefining an existing object. Links leading to the
+ * object do not change, and links leading from it will be recreated
+ * (possibly with some differences from before).
+ *
+ * If skipExtensionDeps is true, we do not delete any dependencies that
+ * show that the given object is a member of an extension. This avoids
+ * needing a lot of extra logic to fetch and recreate that dependency.
+ */
+long
+deleteDependencyRecordsFor(Oid classId, Oid objectId,
+ bool skipExtensionDeps)
+{
+ long count = 0;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ if (skipExtensionDeps &&
+ ((Form_pg_depend) GETSTRUCT(tup))->deptype == DEPENDENCY_EXTENSION)
+ continue;
+
+ CatalogTupleDelete(depRel, &tup->t_self);
+ count++;
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, RowExclusiveLock);
+
+ return count;
+}
+
+/*
+ * deleteDependencyRecordsForClass -- delete all records with given depender
+ * classId/objectId, dependee classId, and deptype.
+ * Returns the number of records deleted.
+ *
+ * This is a variant of deleteDependencyRecordsFor, useful when revoking
+ * an object property that is expressed by a dependency record (such as
+ * extension membership).
+ */
+long
+deleteDependencyRecordsForClass(Oid classId, Oid objectId,
+ Oid refclassId, char deptype)
+{
+ long count = 0;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (depform->refclassid == refclassId && depform->deptype == deptype)
+ {
+ CatalogTupleDelete(depRel, &tup->t_self);
+ count++;
+ }
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, RowExclusiveLock);
+
+ return count;
+}
+
+/*
+ * deleteDependencyRecordsForSpecific -- delete all records with given depender
+ * classId/objectId, dependee classId/objectId, of the given deptype.
+ * Returns the number of records deleted.
+ */
+long
+deleteDependencyRecordsForSpecific(Oid classId, Oid objectId, char deptype,
+ Oid refclassId, Oid refobjectId)
+{
+ long count = 0;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (depform->refclassid == refclassId &&
+ depform->refobjid == refobjectId &&
+ depform->deptype == deptype)
+ {
+ CatalogTupleDelete(depRel, &tup->t_self);
+ count++;
+ }
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, RowExclusiveLock);
+
+ return count;
+}
+
+/*
+ * Adjust dependency record(s) to point to a different object of the same type
+ *
+ * classId/objectId specify the referencing object.
+ * refClassId/oldRefObjectId specify the old referenced object.
+ * newRefObjectId is the new referenced object (must be of class refClassId).
+ *
+ * Note the lack of objsubid parameters. If there are subobject references
+ * they will all be readjusted. Also, there is an expectation that we are
+ * dealing with NORMAL dependencies: if we have to replace an (implicit)
+ * dependency on a pinned object with an explicit dependency on an unpinned
+ * one, the new one will be NORMAL.
+ *
+ * Returns the number of records updated -- zero indicates a problem.
+ */
+long
+changeDependencyFor(Oid classId, Oid objectId,
+ Oid refClassId, Oid oldRefObjectId,
+ Oid newRefObjectId)
+{
+ long count = 0;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+ ObjectAddress objAddr;
+ ObjectAddress depAddr;
+ bool oldIsPinned;
+ bool newIsPinned;
+
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ /*
+ * Check to see if either oldRefObjectId or newRefObjectId is pinned.
+ * Pinned objects should not have any dependency entries pointing to them,
+ * so in these cases we should add or remove a pg_depend entry, or do
+ * nothing at all, rather than update an entry as in the normal case.
+ */
+ objAddr.classId = refClassId;
+ objAddr.objectId = oldRefObjectId;
+ objAddr.objectSubId = 0;
+
+ oldIsPinned = isObjectPinned(&objAddr, depRel);
+
+ objAddr.objectId = newRefObjectId;
+
+ newIsPinned = isObjectPinned(&objAddr, depRel);
+
+ if (oldIsPinned)
+ {
+ table_close(depRel, RowExclusiveLock);
+
+ /*
+ * If both are pinned, we need do nothing. However, return 1 not 0,
+ * else callers will think this is an error case.
+ */
+ if (newIsPinned)
+ return 1;
+
+ /*
+ * There is no old dependency record, but we should insert a new one.
+ * Assume a normal dependency is wanted.
+ */
+ depAddr.classId = classId;
+ depAddr.objectId = objectId;
+ depAddr.objectSubId = 0;
+ recordDependencyOn(&depAddr, &objAddr, DEPENDENCY_NORMAL);
+
+ return 1;
+ }
+
+ /* There should be existing dependency record(s), so search. */
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid((tup = systable_getnext(scan))))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (depform->refclassid == refClassId &&
+ depform->refobjid == oldRefObjectId)
+ {
+ if (newIsPinned)
+ CatalogTupleDelete(depRel, &tup->t_self);
+ else
+ {
+ /* make a modifiable copy */
+ tup = heap_copytuple(tup);
+ depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ depform->refobjid = newRefObjectId;
+
+ CatalogTupleUpdate(depRel, &tup->t_self, tup);
+
+ heap_freetuple(tup);
+ }
+
+ count++;
+ }
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, RowExclusiveLock);
+
+ return count;
+}
+
+/*
+ * Adjust all dependency records to come from a different object of the same type
+ *
+ * classId/oldObjectId specify the old referencing object.
+ * newObjectId is the new referencing object (must be of class classId).
+ *
+ * Returns the number of records updated.
+ */
+long
+changeDependenciesOf(Oid classId, Oid oldObjectId,
+ Oid newObjectId)
+{
+ long count = 0;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(oldObjectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid((tup = systable_getnext(scan))))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ /* make a modifiable copy */
+ tup = heap_copytuple(tup);
+ depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ depform->objid = newObjectId;
+
+ CatalogTupleUpdate(depRel, &tup->t_self, tup);
+
+ heap_freetuple(tup);
+
+ count++;
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, RowExclusiveLock);
+
+ return count;
+}
+
+/*
+ * Adjust all dependency records to point to a different object of the same type
+ *
+ * refClassId/oldRefObjectId specify the old referenced object.
+ * newRefObjectId is the new referenced object (must be of class refClassId).
+ *
+ * Returns the number of records updated.
+ */
+long
+changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
+ Oid newRefObjectId)
+{
+ long count = 0;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+ ObjectAddress objAddr;
+ bool newIsPinned;
+
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ /*
+ * If oldRefObjectId is pinned, there won't be any dependency entries on
+ * it --- we can't cope in that case. (This isn't really worth expending
+ * code to fix, in current usage; it just means you can't rename stuff out
+ * of pg_catalog, which would likely be a bad move anyway.)
+ */
+ objAddr.classId = refClassId;
+ objAddr.objectId = oldRefObjectId;
+ objAddr.objectSubId = 0;
+
+ if (isObjectPinned(&objAddr, depRel))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot remove dependency on %s because it is a system object",
+ getObjectDescription(&objAddr))));
+
+ /*
+ * We can handle adding a dependency on something pinned, though, since
+ * that just means deleting the dependency entry.
+ */
+ objAddr.objectId = newRefObjectId;
+
+ newIsPinned = isObjectPinned(&objAddr, depRel);
+
+ /* Now search for dependency records */
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(refClassId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(oldRefObjectId));
+
+ scan = systable_beginscan(depRel, DependReferenceIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid((tup = systable_getnext(scan))))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (newIsPinned)
+ CatalogTupleDelete(depRel, &tup->t_self);
+ else
+ {
+ /* make a modifiable copy */
+ tup = heap_copytuple(tup);
+ depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ depform->refobjid = newRefObjectId;
+
+ CatalogTupleUpdate(depRel, &tup->t_self, tup);
+
+ heap_freetuple(tup);
+ }
+
+ count++;
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, RowExclusiveLock);
+
+ return count;
+}
+
+/*
+ * isObjectPinned()
+ *
+ * Test if an object is required for basic database functionality.
+ * Caller must already have opened pg_depend.
+ *
+ * The passed subId, if any, is ignored; we assume that only whole objects
+ * are pinned (and that this implies pinning their components).
+ */
+static bool
+isObjectPinned(const ObjectAddress *object, Relation rel)
+{
+ bool ret = false;
+ SysScanDesc scan;
+ HeapTuple tup;
+ ScanKeyData key[2];
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->classId));
+
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(object->objectId));
+
+ scan = systable_beginscan(rel, DependReferenceIndexId, true,
+ NULL, 2, key);
+
+ /*
+ * Since we won't generate additional pg_depend entries for pinned
+ * objects, there can be at most one entry referencing a pinned object.
+ * Hence, it's sufficient to look at the first returned tuple; we don't
+ * need to loop.
+ */
+ tup = systable_getnext(scan);
+ if (HeapTupleIsValid(tup))
+ {
+ Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (foundDep->deptype == DEPENDENCY_PIN)
+ ret = true;
+ }
+
+ systable_endscan(scan);
+
+ return ret;
+}
+
+
+/*
+ * Various special-purpose lookups and manipulations of pg_depend.
+ */
+
+
+/*
+ * Find the extension containing the specified object, if any
+ *
+ * Returns the OID of the extension, or InvalidOid if the object does not
+ * belong to any extension.
+ *
+ * Extension membership is marked by an EXTENSION dependency from the object
+ * to the extension. Note that the result will be indeterminate if pg_depend
+ * contains links from this object to more than one extension ... but that
+ * should never happen.
+ */
+Oid
+getExtensionOfObject(Oid classId, Oid objectId)
+{
+ Oid result = InvalidOid;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = table_open(DependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid((tup = systable_getnext(scan))))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (depform->refclassid == ExtensionRelationId &&
+ depform->deptype == DEPENDENCY_EXTENSION)
+ {
+ result = depform->refobjid;
+ break; /* no need to keep scanning */
+ }
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Return (possibly NIL) list of extensions that the given object depends on
+ * in DEPENDENCY_AUTO_EXTENSION mode.
+ */
+List *
+getAutoExtensionsOfObject(Oid classId, Oid objectId)
+{
+ List *result = NIL;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = table_open(DependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid((tup = systable_getnext(scan))))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (depform->refclassid == ExtensionRelationId &&
+ depform->deptype == DEPENDENCY_AUTO_EXTENSION)
+ result = lappend_oid(result, depform->refobjid);
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Detect whether a sequence is marked as "owned" by a column
+ *
+ * An ownership marker is an AUTO or INTERNAL dependency from the sequence to the
+ * column. If we find one, store the identity of the owning column
+ * into *tableId and *colId and return true; else return false.
+ *
+ * Note: if there's more than one such pg_depend entry then you get
+ * a random one of them returned into the out parameters. This should
+ * not happen, though.
+ */
+bool
+sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
+{
+ bool ret = false;
+ Relation depRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = table_open(DependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationRelationId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(seqId));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid((tup = systable_getnext(scan))))
+ {
+ Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+ if (depform->refclassid == RelationRelationId &&
+ depform->deptype == deptype)
+ {
+ *tableId = depform->refobjid;
+ *colId = depform->refobjsubid;
+ ret = true;
+ break; /* no need to keep scanning */
+ }
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, AccessShareLock);
+
+ return ret;
+}
+
+/*
+ * Collect a list of OIDs of all sequences owned by the specified relation,
+ * and column if specified. If deptype is not zero, then only find sequences
+ * with the specified dependency type.
+ */
+static List *
+getOwnedSequences_internal(Oid relid, AttrNumber attnum, char deptype)
+{
+ List *result = NIL;
+ Relation depRel;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ depRel = table_open(DependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationRelationId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ if (attnum)
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_refobjsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(attnum));
+
+ scan = systable_beginscan(depRel, DependReferenceIndexId, true,
+ NULL, attnum ? 3 : 2, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
+
+ /*
+ * We assume any auto or internal dependency of a sequence on a column
+ * must be what we are looking for. (We need the relkind test because
+ * indexes can also have auto dependencies on columns.)
+ */
+ if (deprec->classid == RelationRelationId &&
+ deprec->objsubid == 0 &&
+ deprec->refobjsubid != 0 &&
+ (deprec->deptype == DEPENDENCY_AUTO || deprec->deptype == DEPENDENCY_INTERNAL) &&
+ get_rel_relkind(deprec->objid) == RELKIND_SEQUENCE)
+ {
+ if (!deptype || deprec->deptype == deptype)
+ result = lappend_oid(result, deprec->objid);
+ }
+ }
+
+ systable_endscan(scan);
+
+ table_close(depRel, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Collect a list of OIDs of all sequences owned (identity or serial) by the
+ * specified relation.
+ */
+List *
+getOwnedSequences(Oid relid)
+{
+ return getOwnedSequences_internal(relid, 0, 0);
+}
+
+/*
+ * Get owned identity sequence, error if not exactly one.
+ */
+Oid
+getIdentitySequence(Oid relid, AttrNumber attnum, bool missing_ok)
+{
+ List *seqlist = getOwnedSequences_internal(relid, attnum, DEPENDENCY_INTERNAL);
+
+ if (list_length(seqlist) > 1)
+ elog(ERROR, "more than one owned sequence found");
+ else if (list_length(seqlist) < 1)
+ {
+ if (missing_ok)
+ return InvalidOid;
+ else
+ elog(ERROR, "no owned sequence found");
+ }
+
+ return linitial_oid(seqlist);
+}
+
+/*
+ * get_constraint_index
+ * Given the OID of a unique, primary-key, or exclusion constraint,
+ * return the OID of the underlying index.
+ *
+ * Return InvalidOid if the index couldn't be found; this suggests the
+ * given OID is bogus, but we leave it to caller to decide what to do.
+ */
+Oid
+get_constraint_index(Oid constraintId)
+{
+ Oid indexId = InvalidOid;
+ Relation depRel;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Search the dependency table for the dependent index */
+ depRel = table_open(DependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(ConstraintRelationId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(constraintId));
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_refobjsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(0));
+
+ scan = systable_beginscan(depRel, DependReferenceIndexId, true,
+ NULL, 3, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
+
+ /*
+ * We assume any internal dependency of an index on the constraint
+ * must be what we are looking for.
+ */
+ if (deprec->classid == RelationRelationId &&
+ deprec->objsubid == 0 &&
+ deprec->deptype == DEPENDENCY_INTERNAL)
+ {
+ char relkind = get_rel_relkind(deprec->objid);
+
+ /*
+ * This is pure paranoia; there shouldn't be any other relkinds
+ * dependent on a constraint.
+ */
+ if (relkind != RELKIND_INDEX &&
+ relkind != RELKIND_PARTITIONED_INDEX)
+ continue;
+
+ indexId = deprec->objid;
+ break;
+ }
+ }
+
+ systable_endscan(scan);
+ table_close(depRel, AccessShareLock);
+
+ return indexId;
+}
+
+/*
+ * get_index_constraint
+ * Given the OID of an index, return the OID of the owning unique,
+ * primary-key, or exclusion constraint, or InvalidOid if there
+ * is no owning constraint.
+ */
+Oid
+get_index_constraint(Oid indexId)
+{
+ Oid constraintId = InvalidOid;
+ Relation depRel;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Search the dependency table for the index */
+ depRel = table_open(DependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationRelationId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(indexId));
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(0));
+
+ scan = systable_beginscan(depRel, DependDependerIndexId, true,
+ NULL, 3, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
+
+ /*
+ * We assume any internal dependency on a constraint must be what we
+ * are looking for.
+ */
+ if (deprec->refclassid == ConstraintRelationId &&
+ deprec->refobjsubid == 0 &&
+ deprec->deptype == DEPENDENCY_INTERNAL)
+ {
+ constraintId = deprec->refobjid;
+ break;
+ }
+ }
+
+ systable_endscan(scan);
+ table_close(depRel, AccessShareLock);
+
+ return constraintId;
+}
+
+/*
+ * get_index_ref_constraints
+ * Given the OID of an index, return the OID of all foreign key
+ * constraints which reference the index.
+ */
+List *
+get_index_ref_constraints(Oid indexId)
+{
+ List *result = NIL;
+ Relation depRel;
+ ScanKeyData key[3];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Search the dependency table for the index */
+ depRel = table_open(DependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_depend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(RelationRelationId));
+ ScanKeyInit(&key[1],
+ Anum_pg_depend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(indexId));
+ ScanKeyInit(&key[2],
+ Anum_pg_depend_refobjsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(0));
+
+ scan = systable_beginscan(depRel, DependReferenceIndexId, true,
+ NULL, 3, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
+
+ /*
+ * We assume any normal dependency from a constraint must be what we
+ * are looking for.
+ */
+ if (deprec->classid == ConstraintRelationId &&
+ deprec->objsubid == 0 &&
+ deprec->deptype == DEPENDENCY_NORMAL)
+ {
+ result = lappend_oid(result, deprec->objid);
+ }
+ }
+
+ systable_endscan(scan);
+ table_close(depRel, AccessShareLock);
+
+ return result;
+}
diff --git a/src/backend/catalog/pg_depend_d.h b/src/backend/catalog/pg_depend_d.h
new file mode 100644
index 0000000..c0bbe9a
--- /dev/null
+++ b/src/backend/catalog/pg_depend_d.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_depend_d.h
+ * Macro definitions for pg_depend
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DEPEND_D_H
+#define PG_DEPEND_D_H
+
+#define DependRelationId 2608
+
+#define Anum_pg_depend_classid 1
+#define Anum_pg_depend_objid 2
+#define Anum_pg_depend_objsubid 3
+#define Anum_pg_depend_refclassid 4
+#define Anum_pg_depend_refobjid 5
+#define Anum_pg_depend_refobjsubid 6
+#define Anum_pg_depend_deptype 7
+
+#define Natts_pg_depend 7
+
+
+#endif /* PG_DEPEND_D_H */
diff --git a/src/backend/catalog/pg_description_d.h b/src/backend/catalog/pg_description_d.h
new file mode 100644
index 0000000..583dc98
--- /dev/null
+++ b/src/backend/catalog/pg_description_d.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_description_d.h
+ * Macro definitions for pg_description
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_DESCRIPTION_D_H
+#define PG_DESCRIPTION_D_H
+
+#define DescriptionRelationId 2609
+
+#define Anum_pg_description_objoid 1
+#define Anum_pg_description_classoid 2
+#define Anum_pg_description_objsubid 3
+#define Anum_pg_description_description 4
+
+#define Natts_pg_description 4
+
+
+#endif /* PG_DESCRIPTION_D_H */
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
new file mode 100644
index 0000000..27e4100
--- /dev/null
+++ b/src/backend/catalog/pg_enum.c
@@ -0,0 +1,761 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_enum.c
+ * routines to support manipulation of the pg_enum relation
+ *
+ * Copyright (c) 2006-2020, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_enum.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "access/xact.h"
+#include "catalog/binary_upgrade.h"
+#include "catalog/catalog.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_enum.h"
+#include "catalog/pg_type.h"
+#include "miscadmin.h"
+#include "nodes/value.h"
+#include "storage/lmgr.h"
+#include "utils/builtins.h"
+#include "utils/catcache.h"
+#include "utils/fmgroids.h"
+#include "utils/hsearch.h"
+#include "utils/memutils.h"
+#include "utils/syscache.h"
+
+/* Potentially set by pg_upgrade_support functions */
+Oid binary_upgrade_next_pg_enum_oid = InvalidOid;
+
+/*
+ * Hash table of enum value OIDs created during the current transaction by
+ * AddEnumLabel. We disallow using these values until the transaction is
+ * committed; otherwise, they might get into indexes where we can't clean
+ * them up, and then if the transaction rolls back we have a broken index.
+ * (See comments for check_safe_enum_use() in enum.c.) Values created by
+ * EnumValuesCreate are *not* blacklisted; we assume those are created during
+ * CREATE TYPE, so they can't go away unless the enum type itself does.
+ */
+static HTAB *enum_blacklist = NULL;
+
+static void RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems);
+static int sort_order_cmp(const void *p1, const void *p2);
+
+
+/*
+ * EnumValuesCreate
+ * Create an entry in pg_enum for each of the supplied enum values.
+ *
+ * vals is a list of Value strings.
+ */
+void
+EnumValuesCreate(Oid enumTypeOid, List *vals)
+{
+ Relation pg_enum;
+ NameData enumlabel;
+ Oid *oids;
+ int elemno,
+ num_elems;
+ Datum values[Natts_pg_enum];
+ bool nulls[Natts_pg_enum];
+ ListCell *lc;
+ HeapTuple tup;
+
+ num_elems = list_length(vals);
+
+ /*
+ * We do not bother to check the list of values for duplicates --- if you
+ * have any, you'll get a less-than-friendly unique-index violation. It is
+ * probably not worth trying harder.
+ */
+
+ pg_enum = table_open(EnumRelationId, RowExclusiveLock);
+
+ /*
+ * Allocate OIDs for the enum's members.
+ *
+ * While this method does not absolutely guarantee that we generate no
+ * duplicate OIDs (since we haven't entered each oid into the table before
+ * allocating the next), trouble could only occur if the OID counter wraps
+ * all the way around before we finish. Which seems unlikely.
+ */
+ oids = (Oid *) palloc(num_elems * sizeof(Oid));
+
+ for (elemno = 0; elemno < num_elems; elemno++)
+ {
+ /*
+ * We assign even-numbered OIDs to all the new enum labels. This
+ * tells the comparison functions the OIDs are in the correct sort
+ * order and can be compared directly.
+ */
+ Oid new_oid;
+
+ do
+ {
+ new_oid = GetNewOidWithIndex(pg_enum, EnumOidIndexId,
+ Anum_pg_enum_oid);
+ } while (new_oid & 1);
+ oids[elemno] = new_oid;
+ }
+
+ /* sort them, just in case OID counter wrapped from high to low */
+ qsort(oids, num_elems, sizeof(Oid), oid_cmp);
+
+ /* and make the entries */
+ memset(nulls, false, sizeof(nulls));
+
+ elemno = 0;
+ foreach(lc, vals)
+ {
+ char *lab = strVal(lfirst(lc));
+
+ /*
+ * labels are stored in a name field, for easier syscache lookup, so
+ * check the length to make sure it's within range.
+ */
+ if (strlen(lab) > (NAMEDATALEN - 1))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("invalid enum label \"%s\"", lab),
+ errdetail("Labels must be %d characters or less.",
+ NAMEDATALEN - 1)));
+
+ values[Anum_pg_enum_oid - 1] = ObjectIdGetDatum(oids[elemno]);
+ values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
+ values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(elemno + 1);
+ namestrcpy(&enumlabel, lab);
+ values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
+
+ tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
+
+ CatalogTupleInsert(pg_enum, tup);
+ heap_freetuple(tup);
+
+ elemno++;
+ }
+
+ /* clean up */
+ pfree(oids);
+ table_close(pg_enum, RowExclusiveLock);
+}
+
+
+/*
+ * EnumValuesDelete
+ * Remove all the pg_enum entries for the specified enum type.
+ */
+void
+EnumValuesDelete(Oid enumTypeOid)
+{
+ Relation pg_enum;
+ ScanKeyData key[1];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ pg_enum = table_open(EnumRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_enum_enumtypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(enumTypeOid));
+
+ scan = systable_beginscan(pg_enum, EnumTypIdLabelIndexId, true,
+ NULL, 1, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ CatalogTupleDelete(pg_enum, &tup->t_self);
+ }
+
+ systable_endscan(scan);
+
+ table_close(pg_enum, RowExclusiveLock);
+}
+
+/*
+ * Initialize the enum blacklist for this transaction.
+ */
+static void
+init_enum_blacklist(void)
+{
+ HASHCTL hash_ctl;
+
+ memset(&hash_ctl, 0, sizeof(hash_ctl));
+ hash_ctl.keysize = sizeof(Oid);
+ hash_ctl.entrysize = sizeof(Oid);
+ hash_ctl.hcxt = TopTransactionContext;
+ enum_blacklist = hash_create("Enum value blacklist",
+ 32,
+ &hash_ctl,
+ HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+}
+
+/*
+ * AddEnumLabel
+ * Add a new label to the enum set. By default it goes at
+ * the end, but the user can choose to place it before or
+ * after any existing set member.
+ */
+void
+AddEnumLabel(Oid enumTypeOid,
+ const char *newVal,
+ const char *neighbor,
+ bool newValIsAfter,
+ bool skipIfExists)
+{
+ Relation pg_enum;
+ Oid newOid;
+ Datum values[Natts_pg_enum];
+ bool nulls[Natts_pg_enum];
+ NameData enumlabel;
+ HeapTuple enum_tup;
+ float4 newelemorder;
+ HeapTuple *existing;
+ CatCList *list;
+ int nelems;
+ int i;
+
+ /* check length of new label is ok */
+ if (strlen(newVal) > (NAMEDATALEN - 1))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("invalid enum label \"%s\"", newVal),
+ errdetail("Labels must be %d characters or less.",
+ NAMEDATALEN - 1)));
+
+ /*
+ * Acquire a lock on the enum type, which we won't release until commit.
+ * This ensures that two backends aren't concurrently modifying the same
+ * enum type. Without that, we couldn't be sure to get a consistent view
+ * of the enum members via the syscache. Note that this does not block
+ * other backends from inspecting the type; see comments for
+ * RenumberEnumType.
+ */
+ LockDatabaseObject(TypeRelationId, enumTypeOid, 0, ExclusiveLock);
+
+ /*
+ * Check if label is already in use. The unique index on pg_enum would
+ * catch this anyway, but we prefer a friendlier error message, and
+ * besides we need a check to support IF NOT EXISTS.
+ */
+ enum_tup = SearchSysCache2(ENUMTYPOIDNAME,
+ ObjectIdGetDatum(enumTypeOid),
+ CStringGetDatum(newVal));
+ if (HeapTupleIsValid(enum_tup))
+ {
+ ReleaseSysCache(enum_tup);
+ if (skipIfExists)
+ {
+ ereport(NOTICE,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("enum label \"%s\" already exists, skipping",
+ newVal)));
+ return;
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("enum label \"%s\" already exists",
+ newVal)));
+ }
+
+ pg_enum = table_open(EnumRelationId, RowExclusiveLock);
+
+ /* If we have to renumber the existing members, we restart from here */
+restart:
+
+ /* Get the list of existing members of the enum */
+ list = SearchSysCacheList1(ENUMTYPOIDNAME,
+ ObjectIdGetDatum(enumTypeOid));
+ nelems = list->n_members;
+
+ /* Sort the existing members by enumsortorder */
+ existing = (HeapTuple *) palloc(nelems * sizeof(HeapTuple));
+ for (i = 0; i < nelems; i++)
+ existing[i] = &(list->members[i]->tuple);
+
+ qsort(existing, nelems, sizeof(HeapTuple), sort_order_cmp);
+
+ if (neighbor == NULL)
+ {
+ /*
+ * Put the new label at the end of the list. No change to existing
+ * tuples is required.
+ */
+ if (nelems > 0)
+ {
+ Form_pg_enum en = (Form_pg_enum) GETSTRUCT(existing[nelems - 1]);
+
+ newelemorder = en->enumsortorder + 1;
+ }
+ else
+ newelemorder = 1;
+ }
+ else
+ {
+ /* BEFORE or AFTER was specified */
+ int nbr_index;
+ int other_nbr_index;
+ Form_pg_enum nbr_en;
+ Form_pg_enum other_nbr_en;
+
+ /* Locate the neighbor element */
+ for (nbr_index = 0; nbr_index < nelems; nbr_index++)
+ {
+ Form_pg_enum en = (Form_pg_enum) GETSTRUCT(existing[nbr_index]);
+
+ if (strcmp(NameStr(en->enumlabel), neighbor) == 0)
+ break;
+ }
+ if (nbr_index >= nelems)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("\"%s\" is not an existing enum label",
+ neighbor)));
+ nbr_en = (Form_pg_enum) GETSTRUCT(existing[nbr_index]);
+
+ /*
+ * Attempt to assign an appropriate enumsortorder value: one less than
+ * the smallest member, one more than the largest member, or halfway
+ * between two existing members.
+ *
+ * In the "halfway" case, because of the finite precision of float4,
+ * we might compute a value that's actually equal to one or the other
+ * of its neighbors. In that case we renumber the existing members
+ * and try again.
+ */
+ if (newValIsAfter)
+ other_nbr_index = nbr_index + 1;
+ else
+ other_nbr_index = nbr_index - 1;
+
+ if (other_nbr_index < 0)
+ newelemorder = nbr_en->enumsortorder - 1;
+ else if (other_nbr_index >= nelems)
+ newelemorder = nbr_en->enumsortorder + 1;
+ else
+ {
+ /*
+ * The midpoint value computed here has to be rounded to float4
+ * precision, else our equality comparisons against the adjacent
+ * values are meaningless. The most portable way of forcing that
+ * to happen with non-C-standard-compliant compilers is to store
+ * it into a volatile variable.
+ */
+ volatile float4 midpoint;
+
+ other_nbr_en = (Form_pg_enum) GETSTRUCT(existing[other_nbr_index]);
+ midpoint = (nbr_en->enumsortorder +
+ other_nbr_en->enumsortorder) / 2;
+
+ if (midpoint == nbr_en->enumsortorder ||
+ midpoint == other_nbr_en->enumsortorder)
+ {
+ RenumberEnumType(pg_enum, existing, nelems);
+ /* Clean up and start over */
+ pfree(existing);
+ ReleaseCatCacheList(list);
+ goto restart;
+ }
+
+ newelemorder = midpoint;
+ }
+ }
+
+ /* Get a new OID for the new label */
+ if (IsBinaryUpgrade)
+ {
+ if (!OidIsValid(binary_upgrade_next_pg_enum_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("pg_enum OID value not set when in binary upgrade mode")));
+
+ /*
+ * Use binary-upgrade override for pg_enum.oid, if supplied. During
+ * binary upgrade, all pg_enum.oid's are set this way so they are
+ * guaranteed to be consistent.
+ */
+ if (neighbor != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("ALTER TYPE ADD BEFORE/AFTER is incompatible with binary upgrade")));
+
+ newOid = binary_upgrade_next_pg_enum_oid;
+ binary_upgrade_next_pg_enum_oid = InvalidOid;
+ }
+ else
+ {
+ /*
+ * Normal case: we need to allocate a new Oid for the value.
+ *
+ * We want to give the new element an even-numbered Oid if it's safe,
+ * which is to say it compares correctly to all pre-existing even
+ * numbered Oids in the enum. Otherwise, we must give it an odd Oid.
+ */
+ for (;;)
+ {
+ bool sorts_ok;
+
+ /* Get a new OID (different from all existing pg_enum tuples) */
+ newOid = GetNewOidWithIndex(pg_enum, EnumOidIndexId,
+ Anum_pg_enum_oid);
+
+ /*
+ * Detect whether it sorts correctly relative to existing
+ * even-numbered labels of the enum. We can ignore existing
+ * labels with odd Oids, since a comparison involving one of those
+ * will not take the fast path anyway.
+ */
+ sorts_ok = true;
+ for (i = 0; i < nelems; i++)
+ {
+ HeapTuple exists_tup = existing[i];
+ Form_pg_enum exists_en = (Form_pg_enum) GETSTRUCT(exists_tup);
+ Oid exists_oid = exists_en->oid;
+
+ if (exists_oid & 1)
+ continue; /* ignore odd Oids */
+
+ if (exists_en->enumsortorder < newelemorder)
+ {
+ /* should sort before */
+ if (exists_oid >= newOid)
+ {
+ sorts_ok = false;
+ break;
+ }
+ }
+ else
+ {
+ /* should sort after */
+ if (exists_oid <= newOid)
+ {
+ sorts_ok = false;
+ break;
+ }
+ }
+ }
+
+ if (sorts_ok)
+ {
+ /* If it's even and sorts OK, we're done. */
+ if ((newOid & 1) == 0)
+ break;
+
+ /*
+ * If it's odd, and sorts OK, loop back to get another OID and
+ * try again. Probably, the next available even OID will sort
+ * correctly too, so it's worth trying.
+ */
+ }
+ else
+ {
+ /*
+ * If it's odd, and does not sort correctly, we're done.
+ * (Probably, the next available even OID would sort
+ * incorrectly too, so no point in trying again.)
+ */
+ if (newOid & 1)
+ break;
+
+ /*
+ * If it's even, and does not sort correctly, loop back to get
+ * another OID and try again. (We *must* reject this case.)
+ */
+ }
+ }
+ }
+
+ /* Done with info about existing members */
+ pfree(existing);
+ ReleaseCatCacheList(list);
+
+ /* Create the new pg_enum entry */
+ memset(nulls, false, sizeof(nulls));
+ values[Anum_pg_enum_oid - 1] = ObjectIdGetDatum(newOid);
+ values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
+ values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(newelemorder);
+ namestrcpy(&enumlabel, newVal);
+ values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
+ enum_tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
+ CatalogTupleInsert(pg_enum, enum_tup);
+ heap_freetuple(enum_tup);
+
+ table_close(pg_enum, RowExclusiveLock);
+
+ /* Set up the blacklist hash if not already done in this transaction */
+ if (enum_blacklist == NULL)
+ init_enum_blacklist();
+
+ /* Add the new value to the blacklist */
+ (void) hash_search(enum_blacklist, &newOid, HASH_ENTER, NULL);
+}
+
+
+/*
+ * RenameEnumLabel
+ * Rename a label in an enum set.
+ */
+void
+RenameEnumLabel(Oid enumTypeOid,
+ const char *oldVal,
+ const char *newVal)
+{
+ Relation pg_enum;
+ HeapTuple enum_tup;
+ Form_pg_enum en;
+ CatCList *list;
+ int nelems;
+ HeapTuple old_tup;
+ bool found_new;
+ int i;
+
+ /* check length of new label is ok */
+ if (strlen(newVal) > (NAMEDATALEN - 1))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("invalid enum label \"%s\"", newVal),
+ errdetail("Labels must be %d characters or less.",
+ NAMEDATALEN - 1)));
+
+ /*
+ * Acquire a lock on the enum type, which we won't release until commit.
+ * This ensures that two backends aren't concurrently modifying the same
+ * enum type. Since we are not changing the type's sort order, this is
+ * probably not really necessary, but there seems no reason not to take
+ * the lock to be sure.
+ */
+ LockDatabaseObject(TypeRelationId, enumTypeOid, 0, ExclusiveLock);
+
+ pg_enum = table_open(EnumRelationId, RowExclusiveLock);
+
+ /* Get the list of existing members of the enum */
+ list = SearchSysCacheList1(ENUMTYPOIDNAME,
+ ObjectIdGetDatum(enumTypeOid));
+ nelems = list->n_members;
+
+ /*
+ * Locate the element to rename and check if the new label is already in
+ * use. (The unique index on pg_enum would catch that anyway, but we
+ * prefer a friendlier error message.)
+ */
+ old_tup = NULL;
+ found_new = false;
+ for (i = 0; i < nelems; i++)
+ {
+ enum_tup = &(list->members[i]->tuple);
+ en = (Form_pg_enum) GETSTRUCT(enum_tup);
+ if (strcmp(NameStr(en->enumlabel), oldVal) == 0)
+ old_tup = enum_tup;
+ if (strcmp(NameStr(en->enumlabel), newVal) == 0)
+ found_new = true;
+ }
+ if (!old_tup)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("\"%s\" is not an existing enum label",
+ oldVal)));
+ if (found_new)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("enum label \"%s\" already exists",
+ newVal)));
+
+ /* OK, make a writable copy of old tuple */
+ enum_tup = heap_copytuple(old_tup);
+ en = (Form_pg_enum) GETSTRUCT(enum_tup);
+
+ ReleaseCatCacheList(list);
+
+ /* Update the pg_enum entry */
+ namestrcpy(&en->enumlabel, newVal);
+ CatalogTupleUpdate(pg_enum, &enum_tup->t_self, enum_tup);
+ heap_freetuple(enum_tup);
+
+ table_close(pg_enum, RowExclusiveLock);
+}
+
+
+/*
+ * Test if the given enum value is on the blacklist
+ */
+bool
+EnumBlacklisted(Oid enum_id)
+{
+ bool found;
+
+ /* If we've made no blacklist table, all values are safe */
+ if (enum_blacklist == NULL)
+ return false;
+
+ /* Else, is it in the table? */
+ (void) hash_search(enum_blacklist, &enum_id, HASH_FIND, &found);
+ return found;
+}
+
+
+/*
+ * Clean up enum stuff after end of top-level transaction.
+ */
+void
+AtEOXact_Enum(void)
+{
+ /*
+ * Reset the blacklist table, as all our enum values are now committed.
+ * The memory will go away automatically when TopTransactionContext is
+ * freed; it's sufficient to clear our pointer.
+ */
+ enum_blacklist = NULL;
+}
+
+
+/*
+ * RenumberEnumType
+ * Renumber existing enum elements to have sort positions 1..n.
+ *
+ * We avoid doing this unless absolutely necessary; in most installations
+ * it will never happen. The reason is that updating existing pg_enum
+ * entries creates hazards for other backends that are concurrently reading
+ * pg_enum. Although system catalog scans now use MVCC semantics, the
+ * syscache machinery might read different pg_enum entries under different
+ * snapshots, so some other backend might get confused about the proper
+ * ordering if a concurrent renumbering occurs.
+ *
+ * We therefore make the following choices:
+ *
+ * 1. Any code that is interested in the enumsortorder values MUST read
+ * all the relevant pg_enum entries with a single MVCC snapshot, or else
+ * acquire lock on the enum type to prevent concurrent execution of
+ * AddEnumLabel().
+ *
+ * 2. Code that is not examining enumsortorder can use a syscache
+ * (for example, enum_in and enum_out do so).
+ */
+static void
+RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems)
+{
+ int i;
+
+ /*
+ * We should only need to increase existing elements' enumsortorders,
+ * never decrease them. Therefore, work from the end backwards, to avoid
+ * unwanted uniqueness violations.
+ */
+ for (i = nelems - 1; i >= 0; i--)
+ {
+ HeapTuple newtup;
+ Form_pg_enum en;
+ float4 newsortorder;
+
+ newtup = heap_copytuple(existing[i]);
+ en = (Form_pg_enum) GETSTRUCT(newtup);
+
+ newsortorder = i + 1;
+ if (en->enumsortorder != newsortorder)
+ {
+ en->enumsortorder = newsortorder;
+
+ CatalogTupleUpdate(pg_enum, &newtup->t_self, newtup);
+ }
+
+ heap_freetuple(newtup);
+ }
+
+ /* Make the updates visible */
+ CommandCounterIncrement();
+}
+
+
+/* qsort comparison function for tuples by sort order */
+static int
+sort_order_cmp(const void *p1, const void *p2)
+{
+ HeapTuple v1 = *((const HeapTuple *) p1);
+ HeapTuple v2 = *((const HeapTuple *) p2);
+ Form_pg_enum en1 = (Form_pg_enum) GETSTRUCT(v1);
+ Form_pg_enum en2 = (Form_pg_enum) GETSTRUCT(v2);
+
+ if (en1->enumsortorder < en2->enumsortorder)
+ return -1;
+ else if (en1->enumsortorder > en2->enumsortorder)
+ return 1;
+ else
+ return 0;
+}
+
+Size
+EstimateEnumBlacklistSpace(void)
+{
+ size_t entries;
+
+ if (enum_blacklist)
+ entries = hash_get_num_entries(enum_blacklist);
+ else
+ entries = 0;
+
+ /* Add one for the terminator. */
+ return sizeof(Oid) * (entries + 1);
+}
+
+void
+SerializeEnumBlacklist(void *space, Size size)
+{
+ Oid *serialized = (Oid *) space;
+
+ /*
+ * Make sure the hash table hasn't changed in size since the caller
+ * reserved the space.
+ */
+ Assert(size == EstimateEnumBlacklistSpace());
+
+ /* Write out all the values from the hash table, if there is one. */
+ if (enum_blacklist)
+ {
+ HASH_SEQ_STATUS status;
+ Oid *value;
+
+ hash_seq_init(&status, enum_blacklist);
+ while ((value = (Oid *) hash_seq_search(&status)))
+ *serialized++ = *value;
+ }
+
+ /* Write out the terminator. */
+ *serialized = InvalidOid;
+
+ /*
+ * Make sure the amount of space we actually used matches what was
+ * estimated.
+ */
+ Assert((char *) (serialized + 1) == ((char *) space) + size);
+}
+
+void
+RestoreEnumBlacklist(void *space)
+{
+ Oid *serialized = (Oid *) space;
+
+ Assert(!enum_blacklist);
+
+ /*
+ * As a special case, if the list is empty then don't even bother to
+ * create the hash table. This is the usual case, since enum alteration
+ * is expected to be rare.
+ */
+ if (!OidIsValid(*serialized))
+ return;
+
+ /* Read all the values into a new hash table. */
+ init_enum_blacklist();
+ do
+ {
+ hash_search(enum_blacklist, serialized++, HASH_ENTER, NULL);
+ } while (OidIsValid(*serialized));
+}
diff --git a/src/backend/catalog/pg_enum_d.h b/src/backend/catalog/pg_enum_d.h
new file mode 100644
index 0000000..cda305a
--- /dev/null
+++ b/src/backend/catalog/pg_enum_d.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_enum_d.h
+ * Macro definitions for pg_enum
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_ENUM_D_H
+#define PG_ENUM_D_H
+
+#define EnumRelationId 3501
+
+#define Anum_pg_enum_oid 1
+#define Anum_pg_enum_enumtypid 2
+#define Anum_pg_enum_enumsortorder 3
+#define Anum_pg_enum_enumlabel 4
+
+#define Natts_pg_enum 4
+
+
+#endif /* PG_ENUM_D_H */
diff --git a/src/backend/catalog/pg_event_trigger_d.h b/src/backend/catalog/pg_event_trigger_d.h
new file mode 100644
index 0000000..aa8aaa2
--- /dev/null
+++ b/src/backend/catalog/pg_event_trigger_d.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_event_trigger_d.h
+ * Macro definitions for pg_event_trigger
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_EVENT_TRIGGER_D_H
+#define PG_EVENT_TRIGGER_D_H
+
+#define EventTriggerRelationId 3466
+
+#define Anum_pg_event_trigger_oid 1
+#define Anum_pg_event_trigger_evtname 2
+#define Anum_pg_event_trigger_evtevent 3
+#define Anum_pg_event_trigger_evtowner 4
+#define Anum_pg_event_trigger_evtfoid 5
+#define Anum_pg_event_trigger_evtenabled 6
+#define Anum_pg_event_trigger_evttags 7
+
+#define Natts_pg_event_trigger 7
+
+
+#endif /* PG_EVENT_TRIGGER_D_H */
diff --git a/src/backend/catalog/pg_extension_d.h b/src/backend/catalog/pg_extension_d.h
new file mode 100644
index 0000000..fe36244
--- /dev/null
+++ b/src/backend/catalog/pg_extension_d.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_extension_d.h
+ * Macro definitions for pg_extension
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_EXTENSION_D_H
+#define PG_EXTENSION_D_H
+
+#define ExtensionRelationId 3079
+
+#define Anum_pg_extension_oid 1
+#define Anum_pg_extension_extname 2
+#define Anum_pg_extension_extowner 3
+#define Anum_pg_extension_extnamespace 4
+#define Anum_pg_extension_extrelocatable 5
+#define Anum_pg_extension_extversion 6
+#define Anum_pg_extension_extconfig 7
+#define Anum_pg_extension_extcondition 8
+
+#define Natts_pg_extension 8
+
+
+#endif /* PG_EXTENSION_D_H */
diff --git a/src/backend/catalog/pg_foreign_data_wrapper_d.h b/src/backend/catalog/pg_foreign_data_wrapper_d.h
new file mode 100644
index 0000000..7921677
--- /dev/null
+++ b/src/backend/catalog/pg_foreign_data_wrapper_d.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_foreign_data_wrapper_d.h
+ * Macro definitions for pg_foreign_data_wrapper
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_FOREIGN_DATA_WRAPPER_D_H
+#define PG_FOREIGN_DATA_WRAPPER_D_H
+
+#define ForeignDataWrapperRelationId 2328
+
+#define Anum_pg_foreign_data_wrapper_oid 1
+#define Anum_pg_foreign_data_wrapper_fdwname 2
+#define Anum_pg_foreign_data_wrapper_fdwowner 3
+#define Anum_pg_foreign_data_wrapper_fdwhandler 4
+#define Anum_pg_foreign_data_wrapper_fdwvalidator 5
+#define Anum_pg_foreign_data_wrapper_fdwacl 6
+#define Anum_pg_foreign_data_wrapper_fdwoptions 7
+
+#define Natts_pg_foreign_data_wrapper 7
+
+
+#endif /* PG_FOREIGN_DATA_WRAPPER_D_H */
diff --git a/src/backend/catalog/pg_foreign_server_d.h b/src/backend/catalog/pg_foreign_server_d.h
new file mode 100644
index 0000000..7164795
--- /dev/null
+++ b/src/backend/catalog/pg_foreign_server_d.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_foreign_server_d.h
+ * Macro definitions for pg_foreign_server
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_FOREIGN_SERVER_D_H
+#define PG_FOREIGN_SERVER_D_H
+
+#define ForeignServerRelationId 1417
+
+#define Anum_pg_foreign_server_oid 1
+#define Anum_pg_foreign_server_srvname 2
+#define Anum_pg_foreign_server_srvowner 3
+#define Anum_pg_foreign_server_srvfdw 4
+#define Anum_pg_foreign_server_srvtype 5
+#define Anum_pg_foreign_server_srvversion 6
+#define Anum_pg_foreign_server_srvacl 7
+#define Anum_pg_foreign_server_srvoptions 8
+
+#define Natts_pg_foreign_server 8
+
+
+#endif /* PG_FOREIGN_SERVER_D_H */
diff --git a/src/backend/catalog/pg_foreign_table_d.h b/src/backend/catalog/pg_foreign_table_d.h
new file mode 100644
index 0000000..2638228
--- /dev/null
+++ b/src/backend/catalog/pg_foreign_table_d.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_foreign_table_d.h
+ * Macro definitions for pg_foreign_table
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_FOREIGN_TABLE_D_H
+#define PG_FOREIGN_TABLE_D_H
+
+#define ForeignTableRelationId 3118
+
+#define Anum_pg_foreign_table_ftrelid 1
+#define Anum_pg_foreign_table_ftserver 2
+#define Anum_pg_foreign_table_ftoptions 3
+
+#define Natts_pg_foreign_table 3
+
+
+#endif /* PG_FOREIGN_TABLE_D_H */
diff --git a/src/backend/catalog/pg_index_d.h b/src/backend/catalog/pg_index_d.h
new file mode 100644
index 0000000..80835e7
--- /dev/null
+++ b/src/backend/catalog/pg_index_d.h
@@ -0,0 +1,56 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_index_d.h
+ * Macro definitions for pg_index
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_INDEX_D_H
+#define PG_INDEX_D_H
+
+#define IndexRelationId 2610
+
+#define Anum_pg_index_indexrelid 1
+#define Anum_pg_index_indrelid 2
+#define Anum_pg_index_indnatts 3
+#define Anum_pg_index_indnkeyatts 4
+#define Anum_pg_index_indisunique 5
+#define Anum_pg_index_indisprimary 6
+#define Anum_pg_index_indisexclusion 7
+#define Anum_pg_index_indimmediate 8
+#define Anum_pg_index_indisclustered 9
+#define Anum_pg_index_indisvalid 10
+#define Anum_pg_index_indcheckxmin 11
+#define Anum_pg_index_indisready 12
+#define Anum_pg_index_indislive 13
+#define Anum_pg_index_indisreplident 14
+#define Anum_pg_index_indkey 15
+#define Anum_pg_index_indcollation 16
+#define Anum_pg_index_indclass 17
+#define Anum_pg_index_indoption 18
+#define Anum_pg_index_indexprs 19
+#define Anum_pg_index_indpred 20
+
+#define Natts_pg_index 20
+
+
+/*
+ * Index AMs that support ordered scans must support these two indoption
+ * bits. Otherwise, the content of the per-column indoption fields is
+ * open for future definition.
+ */
+#define INDOPTION_DESC 0x0001 /* values are in reverse order */
+#define INDOPTION_NULLS_FIRST 0x0002 /* NULLs are first instead of last */
+
+
+#endif /* PG_INDEX_D_H */
diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c
new file mode 100644
index 0000000..5145a56
--- /dev/null
+++ b/src/backend/catalog/pg_inherits.c
@@ -0,0 +1,493 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_inherits.c
+ * routines to support manipulation of the pg_inherits relation
+ *
+ * Note: currently, this module mostly contains inquiry functions; actual
+ * creation and deletion of pg_inherits entries is mostly done in tablecmds.c.
+ * Perhaps someday that code should be moved here, but it'd have to be
+ * disentangled from other stuff such as pg_depend updates.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_inherits.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_inherits.h"
+#include "parser/parse_type.h"
+#include "storage/lmgr.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/memutils.h"
+#include "utils/syscache.h"
+
+/*
+ * Entry of a hash table used in find_all_inheritors. See below.
+ */
+typedef struct SeenRelsEntry
+{
+ Oid rel_id; /* relation oid */
+ int list_index; /* its position in output list(s) */
+} SeenRelsEntry;
+
+/*
+ * find_inheritance_children
+ *
+ * Returns a list containing the OIDs of all relations which
+ * inherit *directly* from the relation with OID 'parentrelId'.
+ *
+ * The specified lock type is acquired on each child relation (but not on the
+ * given rel; caller should already have locked it). If lockmode is NoLock
+ * then no locks are acquired, but caller must beware of race conditions
+ * against possible DROPs of child relations.
+ */
+List *
+find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
+{
+ List *list = NIL;
+ Relation relation;
+ SysScanDesc scan;
+ ScanKeyData key[1];
+ HeapTuple inheritsTuple;
+ Oid inhrelid;
+ Oid *oidarr;
+ int maxoids,
+ numoids,
+ i;
+
+ /*
+ * Can skip the scan if pg_class shows the relation has never had a
+ * subclass.
+ */
+ if (!has_subclass(parentrelId))
+ return NIL;
+
+ /*
+ * Scan pg_inherits and build a working array of subclass OIDs.
+ */
+ maxoids = 32;
+ oidarr = (Oid *) palloc(maxoids * sizeof(Oid));
+ numoids = 0;
+
+ relation = table_open(InheritsRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_inherits_inhparent,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(parentrelId));
+
+ scan = systable_beginscan(relation, InheritsParentIndexId, true,
+ NULL, 1, key);
+
+ while ((inheritsTuple = systable_getnext(scan)) != NULL)
+ {
+ inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;
+ if (numoids >= maxoids)
+ {
+ maxoids *= 2;
+ oidarr = (Oid *) repalloc(oidarr, maxoids * sizeof(Oid));
+ }
+ oidarr[numoids++] = inhrelid;
+ }
+
+ systable_endscan(scan);
+
+ table_close(relation, AccessShareLock);
+
+ /*
+ * If we found more than one child, sort them by OID. This ensures
+ * reasonably consistent behavior regardless of the vagaries of an
+ * indexscan. This is important since we need to be sure all backends
+ * lock children in the same order to avoid needless deadlocks.
+ */
+ if (numoids > 1)
+ qsort(oidarr, numoids, sizeof(Oid), oid_cmp);
+
+ /*
+ * Acquire locks and build the result list.
+ */
+ for (i = 0; i < numoids; i++)
+ {
+ inhrelid = oidarr[i];
+
+ if (lockmode != NoLock)
+ {
+ /* Get the lock to synchronize against concurrent drop */
+ LockRelationOid(inhrelid, lockmode);
+
+ /*
+ * Now that we have the lock, double-check to see if the relation
+ * really exists or not. If not, assume it was dropped while we
+ * waited to acquire lock, and ignore it.
+ */
+ if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(inhrelid)))
+ {
+ /* Release useless lock */
+ UnlockRelationOid(inhrelid, lockmode);
+ /* And ignore this relation */
+ continue;
+ }
+ }
+
+ list = lappend_oid(list, inhrelid);
+ }
+
+ pfree(oidarr);
+
+ return list;
+}
+
+
+/*
+ * find_all_inheritors -
+ * Returns a list of relation OIDs including the given rel plus
+ * all relations that inherit from it, directly or indirectly.
+ * Optionally, it also returns the number of parents found for
+ * each such relation within the inheritance tree rooted at the
+ * given rel.
+ *
+ * The specified lock type is acquired on all child relations (but not on the
+ * given rel; caller should already have locked it). If lockmode is NoLock
+ * then no locks are acquired, but caller must beware of race conditions
+ * against possible DROPs of child relations.
+ */
+List *
+find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
+{
+ /* hash table for O(1) rel_oid -> rel_numparents cell lookup */
+ HTAB *seen_rels;
+ HASHCTL ctl;
+ List *rels_list,
+ *rel_numparents;
+ ListCell *l;
+
+ memset(&ctl, 0, sizeof(ctl));
+ ctl.keysize = sizeof(Oid);
+ ctl.entrysize = sizeof(SeenRelsEntry);
+ ctl.hcxt = CurrentMemoryContext;
+
+ seen_rels = hash_create("find_all_inheritors temporary table",
+ 32, /* start small and extend */
+ &ctl,
+ HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+
+ /*
+ * We build a list starting with the given rel and adding all direct and
+ * indirect children. We can use a single list as both the record of
+ * already-found rels and the agenda of rels yet to be scanned for more
+ * children. This is a bit tricky but works because the foreach() macro
+ * doesn't fetch the next list element until the bottom of the loop. Note
+ * that we can't keep pointers into the output lists; but an index is
+ * sufficient.
+ */
+ rels_list = list_make1_oid(parentrelId);
+ rel_numparents = list_make1_int(0);
+
+ foreach(l, rels_list)
+ {
+ Oid currentrel = lfirst_oid(l);
+ List *currentchildren;
+ ListCell *lc;
+
+ /* Get the direct children of this rel */
+ currentchildren = find_inheritance_children(currentrel, lockmode);
+
+ /*
+ * Add to the queue only those children not already seen. This avoids
+ * making duplicate entries in case of multiple inheritance paths from
+ * the same parent. (It'll also keep us from getting into an infinite
+ * loop, though theoretically there can't be any cycles in the
+ * inheritance graph anyway.)
+ */
+ foreach(lc, currentchildren)
+ {
+ Oid child_oid = lfirst_oid(lc);
+ bool found;
+ SeenRelsEntry *hash_entry;
+
+ hash_entry = hash_search(seen_rels, &child_oid, HASH_ENTER, &found);
+ if (found)
+ {
+ /* if the rel is already there, bump number-of-parents counter */
+ ListCell *numparents_cell;
+
+ numparents_cell = list_nth_cell(rel_numparents,
+ hash_entry->list_index);
+ lfirst_int(numparents_cell)++;
+ }
+ else
+ {
+ /* if it's not there, add it. expect 1 parent, initially. */
+ hash_entry->list_index = list_length(rels_list);
+ rels_list = lappend_oid(rels_list, child_oid);
+ rel_numparents = lappend_int(rel_numparents, 1);
+ }
+ }
+ }
+
+ if (numparents)
+ *numparents = rel_numparents;
+ else
+ list_free(rel_numparents);
+
+ hash_destroy(seen_rels);
+
+ return rels_list;
+}
+
+
+/*
+ * has_subclass - does this relation have any children?
+ *
+ * In the current implementation, has_subclass returns whether a
+ * particular class *might* have a subclass. It will not return the
+ * correct result if a class had a subclass which was later dropped.
+ * This is because relhassubclass in pg_class is not updated immediately
+ * when a subclass is dropped, primarily because of concurrency concerns.
+ *
+ * Currently has_subclass is only used as an efficiency hack to skip
+ * unnecessary inheritance searches, so this is OK. Note that ANALYZE
+ * on a childless table will clean up the obsolete relhassubclass flag.
+ *
+ * Although this doesn't actually touch pg_inherits, it seems reasonable
+ * to keep it here since it's normally used with the other routines here.
+ */
+bool
+has_subclass(Oid relationId)
+{
+ HeapTuple tuple;
+ bool result;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u", relationId);
+
+ result = ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass;
+ ReleaseSysCache(tuple);
+ return result;
+}
+
+/*
+ * has_superclass - does this relation inherit from another?
+ *
+ * Unlike has_subclass, this can be relied on to give an accurate answer.
+ * However, the caller must hold a lock on the given relation so that it
+ * can't be concurrently added to or removed from an inheritance hierarchy.
+ */
+bool
+has_superclass(Oid relationId)
+{
+ Relation catalog;
+ SysScanDesc scan;
+ ScanKeyData skey;
+ bool result;
+
+ catalog = table_open(InheritsRelationId, AccessShareLock);
+ ScanKeyInit(&skey, Anum_pg_inherits_inhrelid, BTEqualStrategyNumber,
+ F_OIDEQ, ObjectIdGetDatum(relationId));
+ scan = systable_beginscan(catalog, InheritsRelidSeqnoIndexId, true,
+ NULL, 1, &skey);
+ result = HeapTupleIsValid(systable_getnext(scan));
+ systable_endscan(scan);
+ table_close(catalog, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Given two type OIDs, determine whether the first is a complex type
+ * (class type) that inherits from the second.
+ *
+ * This essentially asks whether the first type is guaranteed to be coercible
+ * to the second. Therefore, we allow the first type to be a domain over a
+ * complex type that inherits from the second; that creates no difficulties.
+ * But the second type cannot be a domain.
+ */
+bool
+typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
+{
+ bool result = false;
+ Oid subclassRelid;
+ Oid superclassRelid;
+ Relation inhrel;
+ List *visited,
+ *queue;
+ ListCell *queue_item;
+
+ /* We need to work with the associated relation OIDs */
+ subclassRelid = typeOrDomainTypeRelid(subclassTypeId);
+ if (subclassRelid == InvalidOid)
+ return false; /* not a complex type or domain over one */
+ superclassRelid = typeidTypeRelid(superclassTypeId);
+ if (superclassRelid == InvalidOid)
+ return false; /* not a complex type */
+
+ /* No point in searching if the superclass has no subclasses */
+ if (!has_subclass(superclassRelid))
+ return false;
+
+ /*
+ * Begin the search at the relation itself, so add its relid to the queue.
+ */
+ queue = list_make1_oid(subclassRelid);
+ visited = NIL;
+
+ inhrel = table_open(InheritsRelationId, AccessShareLock);
+
+ /*
+ * Use queue to do a breadth-first traversal of the inheritance graph from
+ * the relid supplied up to the root. Notice that we append to the queue
+ * inside the loop --- this is okay because the foreach() macro doesn't
+ * advance queue_item until the next loop iteration begins.
+ */
+ foreach(queue_item, queue)
+ {
+ Oid this_relid = lfirst_oid(queue_item);
+ ScanKeyData skey;
+ SysScanDesc inhscan;
+ HeapTuple inhtup;
+
+ /*
+ * If we've seen this relid already, skip it. This avoids extra work
+ * in multiple-inheritance scenarios, and also protects us from an
+ * infinite loop in case there is a cycle in pg_inherits (though
+ * theoretically that shouldn't happen).
+ */
+ if (list_member_oid(visited, this_relid))
+ continue;
+
+ /*
+ * Okay, this is a not-yet-seen relid. Add it to the list of
+ * already-visited OIDs, then find all the types this relid inherits
+ * from and add them to the queue.
+ */
+ visited = lappend_oid(visited, this_relid);
+
+ ScanKeyInit(&skey,
+ Anum_pg_inherits_inhrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(this_relid));
+
+ inhscan = systable_beginscan(inhrel, InheritsRelidSeqnoIndexId, true,
+ NULL, 1, &skey);
+
+ while ((inhtup = systable_getnext(inhscan)) != NULL)
+ {
+ Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inhtup);
+ Oid inhparent = inh->inhparent;
+
+ /* If this is the target superclass, we're done */
+ if (inhparent == superclassRelid)
+ {
+ result = true;
+ break;
+ }
+
+ /* Else add to queue */
+ queue = lappend_oid(queue, inhparent);
+ }
+
+ systable_endscan(inhscan);
+
+ if (result)
+ break;
+ }
+
+ /* clean up ... */
+ table_close(inhrel, AccessShareLock);
+
+ list_free(visited);
+ list_free(queue);
+
+ return result;
+}
+
+/*
+ * Create a single pg_inherits row with the given data
+ */
+void
+StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber)
+{
+ Datum values[Natts_pg_inherits];
+ bool nulls[Natts_pg_inherits];
+ HeapTuple tuple;
+ Relation inhRelation;
+
+ inhRelation = table_open(InheritsRelationId, RowExclusiveLock);
+
+ /*
+ * Make the pg_inherits entry
+ */
+ values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId);
+ values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid);
+ values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(seqNumber);
+
+ memset(nulls, 0, sizeof(nulls));
+
+ tuple = heap_form_tuple(RelationGetDescr(inhRelation), values, nulls);
+
+ CatalogTupleInsert(inhRelation, tuple);
+
+ heap_freetuple(tuple);
+
+ table_close(inhRelation, RowExclusiveLock);
+}
+
+/*
+ * DeleteInheritsTuple
+ *
+ * Delete pg_inherits tuples with the given inhrelid. inhparent may be given
+ * as InvalidOid, in which case all tuples matching inhrelid are deleted;
+ * otherwise only delete tuples with the specified inhparent.
+ *
+ * Returns whether at least one row was deleted.
+ */
+bool
+DeleteInheritsTuple(Oid inhrelid, Oid inhparent)
+{
+ bool found = false;
+ Relation catalogRelation;
+ ScanKeyData key;
+ SysScanDesc scan;
+ HeapTuple inheritsTuple;
+
+ /*
+ * Find pg_inherits entries by inhrelid.
+ */
+ catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
+ ScanKeyInit(&key,
+ Anum_pg_inherits_inhrelid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(inhrelid));
+ scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
+ true, NULL, 1, &key);
+
+ while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
+ {
+ Oid parent;
+
+ /* Compare inhparent if it was given, and do the actual deletion. */
+ parent = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;
+ if (!OidIsValid(inhparent) || parent == inhparent)
+ {
+ CatalogTupleDelete(catalogRelation, &inheritsTuple->t_self);
+ found = true;
+ }
+ }
+
+ /* Done */
+ systable_endscan(scan);
+ table_close(catalogRelation, RowExclusiveLock);
+
+ return found;
+}
diff --git a/src/backend/catalog/pg_inherits_d.h b/src/backend/catalog/pg_inherits_d.h
new file mode 100644
index 0000000..6028071
--- /dev/null
+++ b/src/backend/catalog/pg_inherits_d.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_inherits_d.h
+ * Macro definitions for pg_inherits
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_INHERITS_D_H
+#define PG_INHERITS_D_H
+
+#define InheritsRelationId 2611
+
+#define Anum_pg_inherits_inhrelid 1
+#define Anum_pg_inherits_inhparent 2
+#define Anum_pg_inherits_inhseqno 3
+
+#define Natts_pg_inherits 3
+
+
+#endif /* PG_INHERITS_D_H */
diff --git a/src/backend/catalog/pg_init_privs_d.h b/src/backend/catalog/pg_init_privs_d.h
new file mode 100644
index 0000000..304fa0a
--- /dev/null
+++ b/src/backend/catalog/pg_init_privs_d.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_init_privs_d.h
+ * Macro definitions for pg_init_privs
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_INIT_PRIVS_D_H
+#define PG_INIT_PRIVS_D_H
+
+#define InitPrivsRelationId 3394
+
+#define Anum_pg_init_privs_objoid 1
+#define Anum_pg_init_privs_classoid 2
+#define Anum_pg_init_privs_objsubid 3
+#define Anum_pg_init_privs_privtype 4
+#define Anum_pg_init_privs_initprivs 5
+
+#define Natts_pg_init_privs 5
+
+
+#endif /* PG_INIT_PRIVS_D_H */
diff --git a/src/backend/catalog/pg_language_d.h b/src/backend/catalog/pg_language_d.h
new file mode 100644
index 0000000..be46167
--- /dev/null
+++ b/src/backend/catalog/pg_language_d.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_language_d.h
+ * Macro definitions for pg_language
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LANGUAGE_D_H
+#define PG_LANGUAGE_D_H
+
+#define LanguageRelationId 2612
+
+#define Anum_pg_language_oid 1
+#define Anum_pg_language_lanname 2
+#define Anum_pg_language_lanowner 3
+#define Anum_pg_language_lanispl 4
+#define Anum_pg_language_lanpltrusted 5
+#define Anum_pg_language_lanplcallfoid 6
+#define Anum_pg_language_laninline 7
+#define Anum_pg_language_lanvalidator 8
+#define Anum_pg_language_lanacl 9
+
+#define Natts_pg_language 9
+
+#define INTERNALlanguageId 12
+#define ClanguageId 13
+#define SQLlanguageId 14
+
+#endif /* PG_LANGUAGE_D_H */
diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c
new file mode 100644
index 0000000..ae9365e
--- /dev/null
+++ b/src/backend/catalog/pg_largeobject.c
@@ -0,0 +1,187 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_largeobject.c
+ * routines to support manipulation of the pg_largeobject relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_largeobject.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/sysattr.h"
+#include "access/table.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_largeobject.h"
+#include "catalog/pg_largeobject_metadata.h"
+#include "miscadmin.h"
+#include "utils/acl.h"
+#include "utils/fmgroids.h"
+#include "utils/rel.h"
+
+
+/*
+ * Create a large object having the given LO identifier.
+ *
+ * We create a new large object by inserting an entry into
+ * pg_largeobject_metadata without any data pages, so that the object
+ * will appear to exist with size 0.
+ */
+Oid
+LargeObjectCreate(Oid loid)
+{
+ Relation pg_lo_meta;
+ HeapTuple ntup;
+ Oid loid_new;
+ Datum values[Natts_pg_largeobject_metadata];
+ bool nulls[Natts_pg_largeobject_metadata];
+
+ pg_lo_meta = table_open(LargeObjectMetadataRelationId,
+ RowExclusiveLock);
+
+ /*
+ * Insert metadata of the largeobject
+ */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+
+ if (OidIsValid(loid))
+ loid_new = loid;
+ else
+ loid_new = GetNewOidWithIndex(pg_lo_meta,
+ LargeObjectMetadataOidIndexId,
+ Anum_pg_largeobject_metadata_oid);
+
+ values[Anum_pg_largeobject_metadata_oid - 1] = ObjectIdGetDatum(loid_new);
+ values[Anum_pg_largeobject_metadata_lomowner - 1]
+ = ObjectIdGetDatum(GetUserId());
+ nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
+
+ ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
+ values, nulls);
+
+ CatalogTupleInsert(pg_lo_meta, ntup);
+
+ heap_freetuple(ntup);
+
+ table_close(pg_lo_meta, RowExclusiveLock);
+
+ return loid_new;
+}
+
+/*
+ * Drop a large object having the given LO identifier. Both the data pages
+ * and metadata must be dropped.
+ */
+void
+LargeObjectDrop(Oid loid)
+{
+ Relation pg_lo_meta;
+ Relation pg_largeobject;
+ ScanKeyData skey[1];
+ SysScanDesc scan;
+ HeapTuple tuple;
+
+ pg_lo_meta = table_open(LargeObjectMetadataRelationId,
+ RowExclusiveLock);
+
+ pg_largeobject = table_open(LargeObjectRelationId,
+ RowExclusiveLock);
+
+ /*
+ * Delete an entry from pg_largeobject_metadata
+ */
+ ScanKeyInit(&skey[0],
+ Anum_pg_largeobject_metadata_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(loid));
+
+ scan = systable_beginscan(pg_lo_meta,
+ LargeObjectMetadataOidIndexId, true,
+ NULL, 1, skey);
+
+ tuple = systable_getnext(scan);
+ if (!HeapTupleIsValid(tuple))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("large object %u does not exist", loid)));
+
+ CatalogTupleDelete(pg_lo_meta, &tuple->t_self);
+
+ systable_endscan(scan);
+
+ /*
+ * Delete all the associated entries from pg_largeobject
+ */
+ ScanKeyInit(&skey[0],
+ Anum_pg_largeobject_loid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(loid));
+
+ scan = systable_beginscan(pg_largeobject,
+ LargeObjectLOidPNIndexId, true,
+ NULL, 1, skey);
+ while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+ {
+ CatalogTupleDelete(pg_largeobject, &tuple->t_self);
+ }
+
+ systable_endscan(scan);
+
+ table_close(pg_largeobject, RowExclusiveLock);
+
+ table_close(pg_lo_meta, RowExclusiveLock);
+}
+
+/*
+ * LargeObjectExists
+ *
+ * We don't use the system cache for large object metadata, for fear of
+ * using too much local memory.
+ *
+ * This function always scans the system catalog using an up-to-date snapshot,
+ * so it should not be used when a large object is opened in read-only mode
+ * (because large objects opened in read only mode are supposed to be viewed
+ * relative to the caller's snapshot, whereas in read-write mode they are
+ * relative to a current snapshot).
+ */
+bool
+LargeObjectExists(Oid loid)
+{
+ Relation pg_lo_meta;
+ ScanKeyData skey[1];
+ SysScanDesc sd;
+ HeapTuple tuple;
+ bool retval = false;
+
+ ScanKeyInit(&skey[0],
+ Anum_pg_largeobject_metadata_oid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(loid));
+
+ pg_lo_meta = table_open(LargeObjectMetadataRelationId,
+ AccessShareLock);
+
+ sd = systable_beginscan(pg_lo_meta,
+ LargeObjectMetadataOidIndexId, true,
+ NULL, 1, skey);
+
+ tuple = systable_getnext(sd);
+ if (HeapTupleIsValid(tuple))
+ retval = true;
+
+ systable_endscan(sd);
+
+ table_close(pg_lo_meta, AccessShareLock);
+
+ return retval;
+}
diff --git a/src/backend/catalog/pg_largeobject_d.h b/src/backend/catalog/pg_largeobject_d.h
new file mode 100644
index 0000000..b9e95f9
--- /dev/null
+++ b/src/backend/catalog/pg_largeobject_d.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_largeobject_d.h
+ * Macro definitions for pg_largeobject
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LARGEOBJECT_D_H
+#define PG_LARGEOBJECT_D_H
+
+#define LargeObjectRelationId 2613
+
+#define Anum_pg_largeobject_loid 1
+#define Anum_pg_largeobject_pageno 2
+#define Anum_pg_largeobject_data 3
+
+#define Natts_pg_largeobject 3
+
+
+#endif /* PG_LARGEOBJECT_D_H */
diff --git a/src/backend/catalog/pg_largeobject_metadata_d.h b/src/backend/catalog/pg_largeobject_metadata_d.h
new file mode 100644
index 0000000..eb4a013
--- /dev/null
+++ b/src/backend/catalog/pg_largeobject_metadata_d.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_largeobject_metadata_d.h
+ * Macro definitions for pg_largeobject_metadata
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LARGEOBJECT_METADATA_D_H
+#define PG_LARGEOBJECT_METADATA_D_H
+
+#define LargeObjectMetadataRelationId 2995
+
+#define Anum_pg_largeobject_metadata_oid 1
+#define Anum_pg_largeobject_metadata_lomowner 2
+#define Anum_pg_largeobject_metadata_lomacl 3
+
+#define Natts_pg_largeobject_metadata 3
+
+
+#endif /* PG_LARGEOBJECT_METADATA_D_H */
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
new file mode 100644
index 0000000..ed85276
--- /dev/null
+++ b/src/backend/catalog/pg_namespace.c
@@ -0,0 +1,120 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_namespace.c
+ * routines to support manipulation of the pg_namespace relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_namespace.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_namespace.h"
+#include "utils/builtins.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+
+/* ----------------
+ * NamespaceCreate
+ *
+ * Create a namespace (schema) with the given name and owner OID.
+ *
+ * If isTemp is true, this schema is a per-backend schema for holding
+ * temporary tables. Currently, it is used to prevent it from being
+ * linked as a member of any active extension. (If someone does CREATE
+ * TEMP TABLE in an extension script, we don't want the temp schema to
+ * become part of the extension). And to avoid checking for default ACL
+ * for temp namespace (as it is not necessary).
+ * ---------------
+ */
+Oid
+NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
+{
+ Relation nspdesc;
+ HeapTuple tup;
+ Oid nspoid;
+ bool nulls[Natts_pg_namespace];
+ Datum values[Natts_pg_namespace];
+ NameData nname;
+ TupleDesc tupDesc;
+ ObjectAddress myself;
+ int i;
+ Acl *nspacl;
+
+ /* sanity checks */
+ if (!nspName)
+ elog(ERROR, "no namespace name supplied");
+
+ /* make sure there is no existing namespace of same name */
+ if (SearchSysCacheExists1(NAMESPACENAME, PointerGetDatum(nspName)))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_SCHEMA),
+ errmsg("schema \"%s\" already exists", nspName)));
+
+ if (!isTemp)
+ nspacl = get_user_default_acl(OBJECT_SCHEMA, ownerId,
+ InvalidOid);
+ else
+ nspacl = NULL;
+
+ nspdesc = table_open(NamespaceRelationId, RowExclusiveLock);
+ tupDesc = nspdesc->rd_att;
+
+ /* initialize nulls and values */
+ for (i = 0; i < Natts_pg_namespace; i++)
+ {
+ nulls[i] = false;
+ values[i] = (Datum) NULL;
+ }
+
+ nspoid = GetNewOidWithIndex(nspdesc, NamespaceOidIndexId,
+ Anum_pg_namespace_oid);
+ values[Anum_pg_namespace_oid - 1] = ObjectIdGetDatum(nspoid);
+ namestrcpy(&nname, nspName);
+ values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
+ values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
+ if (nspacl != NULL)
+ values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(nspacl);
+ else
+ nulls[Anum_pg_namespace_nspacl - 1] = true;
+
+
+ tup = heap_form_tuple(tupDesc, values, nulls);
+
+ CatalogTupleInsert(nspdesc, tup);
+ Assert(OidIsValid(nspoid));
+
+ table_close(nspdesc, RowExclusiveLock);
+
+ /* Record dependencies */
+ myself.classId = NamespaceRelationId;
+ myself.objectId = nspoid;
+ myself.objectSubId = 0;
+
+ /* dependency on owner */
+ recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
+
+ /* dependences on roles mentioned in default ACL */
+ recordDependencyOnNewAcl(NamespaceRelationId, nspoid, 0, ownerId, nspacl);
+
+ /* dependency on extension ... but not for magic temp schemas */
+ if (!isTemp)
+ recordDependencyOnCurrentExtension(&myself, false);
+
+ /* Post creation hook for new schema */
+ InvokeObjectPostCreateHook(NamespaceRelationId, nspoid, 0);
+
+ return nspoid;
+}
diff --git a/src/backend/catalog/pg_namespace_d.h b/src/backend/catalog/pg_namespace_d.h
new file mode 100644
index 0000000..44493fb
--- /dev/null
+++ b/src/backend/catalog/pg_namespace_d.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_namespace_d.h
+ * Macro definitions for pg_namespace
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_NAMESPACE_D_H
+#define PG_NAMESPACE_D_H
+
+#define NamespaceRelationId 2615
+
+#define Anum_pg_namespace_oid 1
+#define Anum_pg_namespace_nspname 2
+#define Anum_pg_namespace_nspowner 3
+#define Anum_pg_namespace_nspacl 4
+
+#define Natts_pg_namespace 4
+
+#define PG_CATALOG_NAMESPACE 11
+#define PG_TOAST_NAMESPACE 99
+#define PG_PUBLIC_NAMESPACE 2200
+
+#endif /* PG_NAMESPACE_D_H */
diff --git a/src/backend/catalog/pg_opclass_d.h b/src/backend/catalog/pg_opclass_d.h
new file mode 100644
index 0000000..bc7b468
--- /dev/null
+++ b/src/backend/catalog/pg_opclass_d.h
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_opclass_d.h
+ * Macro definitions for pg_opclass
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_OPCLASS_D_H
+#define PG_OPCLASS_D_H
+
+#define OperatorClassRelationId 2616
+
+#define Anum_pg_opclass_oid 1
+#define Anum_pg_opclass_opcmethod 2
+#define Anum_pg_opclass_opcname 3
+#define Anum_pg_opclass_opcnamespace 4
+#define Anum_pg_opclass_opcowner 5
+#define Anum_pg_opclass_opcfamily 6
+#define Anum_pg_opclass_opcintype 7
+#define Anum_pg_opclass_opcdefault 8
+#define Anum_pg_opclass_opckeytype 9
+
+#define Natts_pg_opclass 9
+
+#define DATE_BTREE_OPS_OID 3122
+#define FLOAT8_BTREE_OPS_OID 3123
+#define INT2_BTREE_OPS_OID 1979
+#define INT4_BTREE_OPS_OID 1978
+#define INT8_BTREE_OPS_OID 3124
+#define NUMERIC_BTREE_OPS_OID 3125
+#define OID_BTREE_OPS_OID 1981
+#define TEXT_BTREE_OPS_OID 3126
+#define TIMESTAMPTZ_BTREE_OPS_OID 3127
+#define TIMESTAMP_BTREE_OPS_OID 3128
+#define TEXT_BTREE_PATTERN_OPS_OID 4217
+#define VARCHAR_BTREE_PATTERN_OPS_OID 4218
+#define BPCHAR_BTREE_PATTERN_OPS_OID 4219
+
+#endif /* PG_OPCLASS_D_H */
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
new file mode 100644
index 0000000..340e284
--- /dev/null
+++ b/src/backend/catalog/pg_operator.c
@@ -0,0 +1,873 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_operator.c
+ * routines to support manipulation of the pg_operator relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_operator.c
+ *
+ * NOTES
+ * these routines moved here from commands/define.c and somewhat cleaned up.
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "access/xact.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "miscadmin.h"
+#include "parser/parse_oper.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+
+static Oid OperatorGet(const char *operatorName,
+ Oid operatorNamespace,
+ Oid leftObjectId,
+ Oid rightObjectId,
+ bool *defined);
+
+static Oid OperatorLookup(List *operatorName,
+ Oid leftObjectId,
+ Oid rightObjectId,
+ bool *defined);
+
+static Oid OperatorShellMake(const char *operatorName,
+ Oid operatorNamespace,
+ Oid leftTypeId,
+ Oid rightTypeId);
+
+static Oid get_other_operator(List *otherOp,
+ Oid otherLeftTypeId, Oid otherRightTypeId,
+ const char *operatorName, Oid operatorNamespace,
+ Oid leftTypeId, Oid rightTypeId,
+ bool isCommutator);
+
+
+/*
+ * Check whether a proposed operator name is legal
+ *
+ * This had better match the behavior of parser/scan.l!
+ *
+ * We need this because the parser is not smart enough to check that
+ * the arguments of CREATE OPERATOR's COMMUTATOR, NEGATOR, etc clauses
+ * are operator names rather than some other lexical entity.
+ */
+static bool
+validOperatorName(const char *name)
+{
+ size_t len = strlen(name);
+
+ /* Can't be empty or too long */
+ if (len == 0 || len >= NAMEDATALEN)
+ return false;
+
+ /* Can't contain any invalid characters */
+ /* Test string here should match op_chars in scan.l */
+ if (strspn(name, "~!@#^&|`?+-*/%<>=") != len)
+ return false;
+
+ /* Can't contain slash-star or dash-dash (comment starts) */
+ if (strstr(name, "/*") || strstr(name, "--"))
+ return false;
+
+ /*
+ * For SQL standard compatibility, '+' and '-' cannot be the last char of
+ * a multi-char operator unless the operator contains chars that are not
+ * in SQL operators. The idea is to lex '=-' as two operators, but not to
+ * forbid operator names like '?-' that could not be sequences of standard
+ * SQL operators.
+ */
+ if (len > 1 &&
+ (name[len - 1] == '+' ||
+ name[len - 1] == '-'))
+ {
+ int ic;
+
+ for (ic = len - 2; ic >= 0; ic--)
+ {
+ if (strchr("~!@#^&|`?%", name[ic]))
+ break;
+ }
+ if (ic < 0)
+ return false; /* nope, not valid */
+ }
+
+ /* != isn't valid either, because parser will convert it to <> */
+ if (strcmp(name, "!=") == 0)
+ return false;
+
+ return true;
+}
+
+
+/*
+ * OperatorGet
+ *
+ * finds an operator given an exact specification (name, namespace,
+ * left and right type IDs).
+ *
+ * *defined is set true if defined (not a shell)
+ */
+static Oid
+OperatorGet(const char *operatorName,
+ Oid operatorNamespace,
+ Oid leftObjectId,
+ Oid rightObjectId,
+ bool *defined)
+{
+ HeapTuple tup;
+ Oid operatorObjectId;
+
+ tup = SearchSysCache4(OPERNAMENSP,
+ PointerGetDatum(operatorName),
+ ObjectIdGetDatum(leftObjectId),
+ ObjectIdGetDatum(rightObjectId),
+ ObjectIdGetDatum(operatorNamespace));
+ if (HeapTupleIsValid(tup))
+ {
+ Form_pg_operator oprform = (Form_pg_operator) GETSTRUCT(tup);
+
+ operatorObjectId = oprform->oid;
+ *defined = RegProcedureIsValid(oprform->oprcode);
+ ReleaseSysCache(tup);
+ }
+ else
+ {
+ operatorObjectId = InvalidOid;
+ *defined = false;
+ }
+
+ return operatorObjectId;
+}
+
+/*
+ * OperatorLookup
+ *
+ * looks up an operator given a possibly-qualified name and
+ * left and right type IDs.
+ *
+ * *defined is set true if defined (not a shell)
+ */
+static Oid
+OperatorLookup(List *operatorName,
+ Oid leftObjectId,
+ Oid rightObjectId,
+ bool *defined)
+{
+ Oid operatorObjectId;
+ RegProcedure oprcode;
+
+ operatorObjectId = LookupOperName(NULL, operatorName,
+ leftObjectId, rightObjectId,
+ true, -1);
+ if (!OidIsValid(operatorObjectId))
+ {
+ *defined = false;
+ return InvalidOid;
+ }
+
+ oprcode = get_opcode(operatorObjectId);
+ *defined = RegProcedureIsValid(oprcode);
+
+ return operatorObjectId;
+}
+
+
+/*
+ * OperatorShellMake
+ * Make a "shell" entry for a not-yet-existing operator.
+ */
+static Oid
+OperatorShellMake(const char *operatorName,
+ Oid operatorNamespace,
+ Oid leftTypeId,
+ Oid rightTypeId)
+{
+ Relation pg_operator_desc;
+ Oid operatorObjectId;
+ int i;
+ HeapTuple tup;
+ Datum values[Natts_pg_operator];
+ bool nulls[Natts_pg_operator];
+ NameData oname;
+ TupleDesc tupDesc;
+
+ /*
+ * validate operator name
+ */
+ if (!validOperatorName(operatorName))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("\"%s\" is not a valid operator name",
+ operatorName)));
+
+ /*
+ * open pg_operator
+ */
+ pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
+ tupDesc = pg_operator_desc->rd_att;
+
+ /*
+ * initialize our *nulls and *values arrays
+ */
+ for (i = 0; i < Natts_pg_operator; ++i)
+ {
+ nulls[i] = false;
+ values[i] = (Datum) NULL; /* redundant, but safe */
+ }
+
+ /*
+ * initialize values[] with the operator name and input data types. Note
+ * that oprcode is set to InvalidOid, indicating it's a shell.
+ */
+ operatorObjectId = GetNewOidWithIndex(pg_operator_desc, OperatorOidIndexId,
+ Anum_pg_operator_oid);
+ values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId);
+ namestrcpy(&oname, operatorName);
+ values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname);
+ values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace);
+ values[Anum_pg_operator_oprowner - 1] = ObjectIdGetDatum(GetUserId());
+ values[Anum_pg_operator_oprkind - 1] = CharGetDatum(leftTypeId ? (rightTypeId ? 'b' : 'r') : 'l');
+ values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(false);
+ values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(false);
+ values[Anum_pg_operator_oprleft - 1] = ObjectIdGetDatum(leftTypeId);
+ values[Anum_pg_operator_oprright - 1] = ObjectIdGetDatum(rightTypeId);
+ values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid);
+
+ /*
+ * create a new operator tuple
+ */
+ tup = heap_form_tuple(tupDesc, values, nulls);
+
+ /*
+ * insert our "shell" operator tuple
+ */
+ CatalogTupleInsert(pg_operator_desc, tup);
+
+ /* Add dependencies for the entry */
+ makeOperatorDependencies(tup, false);
+
+ heap_freetuple(tup);
+
+ /* Post creation hook for new shell operator */
+ InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0);
+
+ /*
+ * Make sure the tuple is visible for subsequent lookups/updates.
+ */
+ CommandCounterIncrement();
+
+ /*
+ * close the operator relation and return the oid.
+ */
+ table_close(pg_operator_desc, RowExclusiveLock);
+
+ return operatorObjectId;
+}
+
+/*
+ * OperatorCreate
+ *
+ * "X" indicates an optional argument (i.e. one that can be NULL or 0)
+ * operatorName name for new operator
+ * operatorNamespace namespace for new operator
+ * leftTypeId X left type ID
+ * rightTypeId X right type ID
+ * procedureId procedure ID for operator
+ * commutatorName X commutator operator
+ * negatorName X negator operator
+ * restrictionId X restriction selectivity procedure ID
+ * joinId X join selectivity procedure ID
+ * canMerge merge join can be used with this operator
+ * canHash hash join can be used with this operator
+ *
+ * The caller should have validated properties and permissions for the
+ * objects passed as OID references. We must handle the commutator and
+ * negator operator references specially, however, since those need not
+ * exist beforehand.
+ *
+ * This routine gets complicated because it allows the user to
+ * specify operators that do not exist. For example, if operator
+ * "op" is being defined, the negator operator "negop" and the
+ * commutator "commop" can also be defined without specifying
+ * any information other than their names. Since in order to
+ * add "op" to the PG_OPERATOR catalog, all the Oid's for these
+ * operators must be placed in the fields of "op", a forward
+ * declaration is done on the commutator and negator operators.
+ * This is called creating a shell, and its main effect is to
+ * create a tuple in the PG_OPERATOR catalog with minimal
+ * information about the operator (just its name and types).
+ * Forward declaration is used only for this purpose, it is
+ * not available to the user as it is for type definition.
+ */
+ObjectAddress
+OperatorCreate(const char *operatorName,
+ Oid operatorNamespace,
+ Oid leftTypeId,
+ Oid rightTypeId,
+ Oid procedureId,
+ List *commutatorName,
+ List *negatorName,
+ Oid restrictionId,
+ Oid joinId,
+ bool canMerge,
+ bool canHash)
+{
+ Relation pg_operator_desc;
+ HeapTuple tup;
+ bool isUpdate;
+ bool nulls[Natts_pg_operator];
+ bool replaces[Natts_pg_operator];
+ Datum values[Natts_pg_operator];
+ Oid operatorObjectId;
+ bool operatorAlreadyDefined;
+ Oid operResultType;
+ Oid commutatorId,
+ negatorId;
+ bool selfCommutator = false;
+ NameData oname;
+ int i;
+ ObjectAddress address;
+
+ /*
+ * Sanity checks
+ */
+ if (!validOperatorName(operatorName))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("\"%s\" is not a valid operator name",
+ operatorName)));
+
+ if (!(OidIsValid(leftTypeId) && OidIsValid(rightTypeId)))
+ {
+ /* If it's not a binary op, these things mustn't be set: */
+ if (commutatorName)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("only binary operators can have commutators")));
+ if (OidIsValid(joinId))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("only binary operators can have join selectivity")));
+ if (canMerge)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("only binary operators can merge join")));
+ if (canHash)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("only binary operators can hash")));
+ }
+
+ operResultType = get_func_rettype(procedureId);
+
+ if (operResultType != BOOLOID)
+ {
+ /* If it's not a boolean op, these things mustn't be set: */
+ if (negatorName)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("only boolean operators can have negators")));
+ if (OidIsValid(restrictionId))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("only boolean operators can have restriction selectivity")));
+ if (OidIsValid(joinId))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("only boolean operators can have join selectivity")));
+ if (canMerge)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("only boolean operators can merge join")));
+ if (canHash)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("only boolean operators can hash")));
+ }
+
+ operatorObjectId = OperatorGet(operatorName,
+ operatorNamespace,
+ leftTypeId,
+ rightTypeId,
+ &operatorAlreadyDefined);
+
+ if (operatorAlreadyDefined)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_FUNCTION),
+ errmsg("operator %s already exists",
+ operatorName)));
+
+ /*
+ * At this point, if operatorObjectId is not InvalidOid then we are
+ * filling in a previously-created shell. Insist that the user own any
+ * such shell.
+ */
+ if (OidIsValid(operatorObjectId) &&
+ !pg_oper_ownercheck(operatorObjectId, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_OPERATOR,
+ operatorName);
+
+ /*
+ * Set up the other operators. If they do not currently exist, create
+ * shells in order to get ObjectId's.
+ */
+
+ if (commutatorName)
+ {
+ /* commutator has reversed arg types */
+ commutatorId = get_other_operator(commutatorName,
+ rightTypeId, leftTypeId,
+ operatorName, operatorNamespace,
+ leftTypeId, rightTypeId,
+ true);
+
+ /* Permission check: must own other operator */
+ if (OidIsValid(commutatorId) &&
+ !pg_oper_ownercheck(commutatorId, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_OPERATOR,
+ NameListToString(commutatorName));
+
+ /*
+ * self-linkage to this operator; will fix below. Note that only
+ * self-linkage for commutation makes sense.
+ */
+ if (!OidIsValid(commutatorId))
+ selfCommutator = true;
+ }
+ else
+ commutatorId = InvalidOid;
+
+ if (negatorName)
+ {
+ /* negator has same arg types */
+ negatorId = get_other_operator(negatorName,
+ leftTypeId, rightTypeId,
+ operatorName, operatorNamespace,
+ leftTypeId, rightTypeId,
+ false);
+
+ /* Permission check: must own other operator */
+ if (OidIsValid(negatorId) &&
+ !pg_oper_ownercheck(negatorId, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_OPERATOR,
+ NameListToString(negatorName));
+ }
+ else
+ negatorId = InvalidOid;
+
+ /*
+ * set up values in the operator tuple
+ */
+
+ for (i = 0; i < Natts_pg_operator; ++i)
+ {
+ values[i] = (Datum) NULL;
+ replaces[i] = true;
+ nulls[i] = false;
+ }
+
+ namestrcpy(&oname, operatorName);
+ values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname);
+ values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace);
+ values[Anum_pg_operator_oprowner - 1] = ObjectIdGetDatum(GetUserId());
+ values[Anum_pg_operator_oprkind - 1] = CharGetDatum(leftTypeId ? (rightTypeId ? 'b' : 'r') : 'l');
+ values[Anum_pg_operator_oprcanmerge - 1] = BoolGetDatum(canMerge);
+ values[Anum_pg_operator_oprcanhash - 1] = BoolGetDatum(canHash);
+ values[Anum_pg_operator_oprleft - 1] = ObjectIdGetDatum(leftTypeId);
+ values[Anum_pg_operator_oprright - 1] = ObjectIdGetDatum(rightTypeId);
+ values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(operResultType);
+ values[Anum_pg_operator_oprcom - 1] = ObjectIdGetDatum(commutatorId);
+ values[Anum_pg_operator_oprnegate - 1] = ObjectIdGetDatum(negatorId);
+ values[Anum_pg_operator_oprcode - 1] = ObjectIdGetDatum(procedureId);
+ values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionId);
+ values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinId);
+
+ pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
+
+ /*
+ * If we are replacing an operator shell, update; else insert
+ */
+ if (operatorObjectId)
+ {
+ isUpdate = true;
+
+ tup = SearchSysCacheCopy1(OPEROID,
+ ObjectIdGetDatum(operatorObjectId));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for operator %u",
+ operatorObjectId);
+
+ replaces[Anum_pg_operator_oid - 1] = false;
+ tup = heap_modify_tuple(tup,
+ RelationGetDescr(pg_operator_desc),
+ values,
+ nulls,
+ replaces);
+
+ CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
+ }
+ else
+ {
+ isUpdate = false;
+
+ operatorObjectId = GetNewOidWithIndex(pg_operator_desc,
+ OperatorOidIndexId,
+ Anum_pg_operator_oid);
+ values[Anum_pg_operator_oid - 1] = ObjectIdGetDatum(operatorObjectId);
+
+ tup = heap_form_tuple(RelationGetDescr(pg_operator_desc),
+ values, nulls);
+
+ CatalogTupleInsert(pg_operator_desc, tup);
+ }
+
+ /* Add dependencies for the entry */
+ address = makeOperatorDependencies(tup, isUpdate);
+
+ /* Post creation hook for new operator */
+ InvokeObjectPostCreateHook(OperatorRelationId, operatorObjectId, 0);
+
+ table_close(pg_operator_desc, RowExclusiveLock);
+
+ /*
+ * If a commutator and/or negator link is provided, update the other
+ * operator(s) to point at this one, if they don't already have a link.
+ * This supports an alternative style of operator definition wherein the
+ * user first defines one operator without giving negator or commutator,
+ * then defines the other operator of the pair with the proper commutator
+ * or negator attribute. That style doesn't require creation of a shell,
+ * and it's the only style that worked right before Postgres version 6.5.
+ * This code also takes care of the situation where the new operator is
+ * its own commutator.
+ */
+ if (selfCommutator)
+ commutatorId = operatorObjectId;
+
+ if (OidIsValid(commutatorId) || OidIsValid(negatorId))
+ OperatorUpd(operatorObjectId, commutatorId, negatorId, false);
+
+ return address;
+}
+
+/*
+ * Try to lookup another operator (commutator, etc)
+ *
+ * If not found, check to see if it is exactly the operator we are trying
+ * to define; if so, return InvalidOid. (Note that this case is only
+ * sensible for a commutator, so we error out otherwise.) If it is not
+ * the same operator, create a shell operator.
+ */
+static Oid
+get_other_operator(List *otherOp, Oid otherLeftTypeId, Oid otherRightTypeId,
+ const char *operatorName, Oid operatorNamespace,
+ Oid leftTypeId, Oid rightTypeId, bool isCommutator)
+{
+ Oid other_oid;
+ bool otherDefined;
+ char *otherName;
+ Oid otherNamespace;
+ AclResult aclresult;
+
+ other_oid = OperatorLookup(otherOp,
+ otherLeftTypeId,
+ otherRightTypeId,
+ &otherDefined);
+
+ if (OidIsValid(other_oid))
+ {
+ /* other op already in catalogs */
+ return other_oid;
+ }
+
+ otherNamespace = QualifiedNameGetCreationNamespace(otherOp,
+ &otherName);
+
+ if (strcmp(otherName, operatorName) == 0 &&
+ otherNamespace == operatorNamespace &&
+ otherLeftTypeId == leftTypeId &&
+ otherRightTypeId == rightTypeId)
+ {
+ /*
+ * self-linkage to this operator; caller will fix later. Note that
+ * only self-linkage for commutation makes sense.
+ */
+ if (!isCommutator)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("operator cannot be its own negator or sort operator")));
+ return InvalidOid;
+ }
+
+ /* not in catalogs, different from operator, so make shell */
+
+ aclresult = pg_namespace_aclcheck(otherNamespace, GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, OBJECT_SCHEMA,
+ get_namespace_name(otherNamespace));
+
+ other_oid = OperatorShellMake(otherName,
+ otherNamespace,
+ otherLeftTypeId,
+ otherRightTypeId);
+ return other_oid;
+}
+
+/*
+ * OperatorUpd
+ *
+ * For a given operator, look up its negator and commutator operators.
+ * When isDelete is false, update their negator and commutator fields to
+ * point back to the given operator; when isDelete is true, update those
+ * fields to no longer point back to the given operator.
+ *
+ * The !isDelete case solves a problem for users who need to insert two new
+ * operators that are the negator or commutator of each other, while the
+ * isDelete case is needed so as not to leave dangling OID links behind
+ * after dropping an operator.
+ */
+void
+OperatorUpd(Oid baseId, Oid commId, Oid negId, bool isDelete)
+{
+ Relation pg_operator_desc;
+ HeapTuple tup;
+
+ /*
+ * If we're making an operator into its own commutator, then we need a
+ * command-counter increment here, since we've just inserted the tuple
+ * we're about to update. But when we're dropping an operator, we can
+ * skip this because we're at the beginning of the command.
+ */
+ if (!isDelete)
+ CommandCounterIncrement();
+
+ /* Open the relation. */
+ pg_operator_desc = table_open(OperatorRelationId, RowExclusiveLock);
+
+ /* Get a writable copy of the commutator's tuple. */
+ if (OidIsValid(commId))
+ tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(commId));
+ else
+ tup = NULL;
+
+ /* Update the commutator's tuple if need be. */
+ if (HeapTupleIsValid(tup))
+ {
+ Form_pg_operator t = (Form_pg_operator) GETSTRUCT(tup);
+ bool update_commutator = false;
+
+ /*
+ * Out of due caution, we only change the commutator's oprcom field if
+ * it has the exact value we expected: InvalidOid when creating an
+ * operator, or baseId when dropping one.
+ */
+ if (isDelete && t->oprcom == baseId)
+ {
+ t->oprcom = InvalidOid;
+ update_commutator = true;
+ }
+ else if (!isDelete && !OidIsValid(t->oprcom))
+ {
+ t->oprcom = baseId;
+ update_commutator = true;
+ }
+
+ /* If any columns were found to need modification, update tuple. */
+ if (update_commutator)
+ {
+ CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
+
+ /*
+ * Do CCI to make the updated tuple visible. We must do this in
+ * case the commutator is also the negator. (Which would be a
+ * logic error on the operator definer's part, but that's not a
+ * good reason to fail here.) We would need a CCI anyway in the
+ * deletion case for a self-commutator with no negator.
+ */
+ CommandCounterIncrement();
+ }
+ }
+
+ /*
+ * Similarly find and update the negator, if any.
+ */
+ if (OidIsValid(negId))
+ tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(negId));
+ else
+ tup = NULL;
+
+ if (HeapTupleIsValid(tup))
+ {
+ Form_pg_operator t = (Form_pg_operator) GETSTRUCT(tup);
+ bool update_negator = false;
+
+ /*
+ * Out of due caution, we only change the negator's oprnegate field if
+ * it has the exact value we expected: InvalidOid when creating an
+ * operator, or baseId when dropping one.
+ */
+ if (isDelete && t->oprnegate == baseId)
+ {
+ t->oprnegate = InvalidOid;
+ update_negator = true;
+ }
+ else if (!isDelete && !OidIsValid(t->oprnegate))
+ {
+ t->oprnegate = baseId;
+ update_negator = true;
+ }
+
+ /* If any columns were found to need modification, update tuple. */
+ if (update_negator)
+ {
+ CatalogTupleUpdate(pg_operator_desc, &tup->t_self, tup);
+
+ /*
+ * In the deletion case, do CCI to make the updated tuple visible.
+ * We must do this in case the operator is its own negator. (Which
+ * would be a logic error on the operator definer's part, but
+ * that's not a good reason to fail here.)
+ */
+ if (isDelete)
+ CommandCounterIncrement();
+ }
+ }
+
+ /* Close relation and release catalog lock. */
+ table_close(pg_operator_desc, RowExclusiveLock);
+}
+
+/*
+ * Create dependencies for an operator (either a freshly inserted
+ * complete operator, a new shell operator, a just-updated shell,
+ * or an operator that's being modified by ALTER OPERATOR).
+ *
+ * NB: the OidIsValid tests in this routine are necessary, in case
+ * the given operator is a shell.
+ */
+ObjectAddress
+makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
+{
+ Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tuple);
+ ObjectAddress myself,
+ referenced;
+
+ myself.classId = OperatorRelationId;
+ myself.objectId = oper->oid;
+ myself.objectSubId = 0;
+
+ /*
+ * If we are updating the operator, delete any existing entries, except
+ * for extension membership which should remain the same.
+ */
+ if (isUpdate)
+ {
+ deleteDependencyRecordsFor(myself.classId, myself.objectId, true);
+ deleteSharedDependencyRecordsFor(myself.classId, myself.objectId, 0);
+ }
+
+ /* Dependency on namespace */
+ if (OidIsValid(oper->oprnamespace))
+ {
+ referenced.classId = NamespaceRelationId;
+ referenced.objectId = oper->oprnamespace;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on left type */
+ if (OidIsValid(oper->oprleft))
+ {
+ referenced.classId = TypeRelationId;
+ referenced.objectId = oper->oprleft;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on right type */
+ if (OidIsValid(oper->oprright))
+ {
+ referenced.classId = TypeRelationId;
+ referenced.objectId = oper->oprright;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on result type */
+ if (OidIsValid(oper->oprresult))
+ {
+ referenced.classId = TypeRelationId;
+ referenced.objectId = oper->oprresult;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /*
+ * NOTE: we do not consider the operator to depend on the associated
+ * operators oprcom and oprnegate. We would not want to delete this
+ * operator if those go away, but only reset the link fields; which is not
+ * a function that the dependency code can presently handle. (Something
+ * could perhaps be done with objectSubId though.) For now, it's okay to
+ * let those links dangle if a referenced operator is removed.
+ */
+
+ /* Dependency on implementation function */
+ if (OidIsValid(oper->oprcode))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = oper->oprcode;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on restriction selectivity function */
+ if (OidIsValid(oper->oprrest))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = oper->oprrest;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on join selectivity function */
+ if (OidIsValid(oper->oprjoin))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = oper->oprjoin;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Dependency on owner */
+ recordDependencyOnOwner(OperatorRelationId, oper->oid,
+ oper->oprowner);
+
+ /* Dependency on extension */
+ recordDependencyOnCurrentExtension(&myself, true);
+
+ return myself;
+}
diff --git a/src/backend/catalog/pg_operator_d.h b/src/backend/catalog/pg_operator_d.h
new file mode 100644
index 0000000..02a5956
--- /dev/null
+++ b/src/backend/catalog/pg_operator_d.h
@@ -0,0 +1,106 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_operator_d.h
+ * Macro definitions for pg_operator
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_OPERATOR_D_H
+#define PG_OPERATOR_D_H
+
+#define OperatorRelationId 2617
+
+#define Anum_pg_operator_oid 1
+#define Anum_pg_operator_oprname 2
+#define Anum_pg_operator_oprnamespace 3
+#define Anum_pg_operator_oprowner 4
+#define Anum_pg_operator_oprkind 5
+#define Anum_pg_operator_oprcanmerge 6
+#define Anum_pg_operator_oprcanhash 7
+#define Anum_pg_operator_oprleft 8
+#define Anum_pg_operator_oprright 9
+#define Anum_pg_operator_oprresult 10
+#define Anum_pg_operator_oprcom 11
+#define Anum_pg_operator_oprnegate 12
+#define Anum_pg_operator_oprcode 13
+#define Anum_pg_operator_oprrest 14
+#define Anum_pg_operator_oprjoin 15
+
+#define Natts_pg_operator 15
+
+#define BooleanNotEqualOperator 85
+#define BooleanEqualOperator 91
+#define Int4EqualOperator 96
+#define Int4LessOperator 97
+#define TextEqualOperator 98
+#define NameEqualTextOperator 254
+#define NameLessTextOperator 255
+#define NameGreaterEqualTextOperator 257
+#define TIDEqualOperator 387
+#define TIDLessOperator 2799
+#define Int8LessOperator 412
+#define OID_NAME_REGEXEQ_OP 639
+#define OID_TEXT_REGEXEQ_OP 641
+#define TextLessOperator 664
+#define TextGreaterEqualOperator 667
+#define Float8LessOperator 672
+#define BpcharEqualOperator 1054
+#define OID_BPCHAR_REGEXEQ_OP 1055
+#define BpcharLessOperator 1058
+#define BpcharGreaterEqualOperator 1061
+#define ARRAY_EQ_OP 1070
+#define ARRAY_LT_OP 1072
+#define ARRAY_GT_OP 1073
+#define OID_NAME_LIKE_OP 1207
+#define OID_TEXT_LIKE_OP 1209
+#define OID_BPCHAR_LIKE_OP 1211
+#define OID_NAME_ICREGEXEQ_OP 1226
+#define OID_TEXT_ICREGEXEQ_OP 1228
+#define OID_BPCHAR_ICREGEXEQ_OP 1234
+#define OID_INET_SUB_OP 931
+#define OID_INET_SUBEQ_OP 932
+#define OID_INET_SUP_OP 933
+#define OID_INET_SUPEQ_OP 934
+#define OID_INET_OVERLAP_OP 3552
+#define OID_NAME_ICLIKE_OP 1625
+#define OID_TEXT_ICLIKE_OP 1627
+#define OID_BPCHAR_ICLIKE_OP 1629
+#define ByteaEqualOperator 1955
+#define ByteaLessOperator 1957
+#define ByteaGreaterEqualOperator 1960
+#define OID_BYTEA_LIKE_OP 2016
+#define TextPatternLessOperator 2314
+#define TextPatternGreaterEqualOperator 2317
+#define BpcharPatternLessOperator 2326
+#define BpcharPatternGreaterEqualOperator 2329
+#define OID_ARRAY_OVERLAP_OP 2750
+#define OID_ARRAY_CONTAINS_OP 2751
+#define OID_ARRAY_CONTAINED_OP 2752
+#define RECORD_EQ_OP 2988
+#define RECORD_LT_OP 2990
+#define RECORD_GT_OP 2991
+#define OID_RANGE_LESS_OP 3884
+#define OID_RANGE_LESS_EQUAL_OP 3885
+#define OID_RANGE_GREATER_EQUAL_OP 3886
+#define OID_RANGE_GREATER_OP 3887
+#define OID_RANGE_OVERLAP_OP 3888
+#define OID_RANGE_CONTAINS_ELEM_OP 3889
+#define OID_RANGE_CONTAINS_OP 3890
+#define OID_RANGE_ELEM_CONTAINED_OP 3891
+#define OID_RANGE_CONTAINED_OP 3892
+#define OID_RANGE_LEFT_OP 3893
+#define OID_RANGE_RIGHT_OP 3894
+#define OID_RANGE_OVERLAPS_LEFT_OP 3895
+#define OID_RANGE_OVERLAPS_RIGHT_OP 3896
+
+#endif /* PG_OPERATOR_D_H */
diff --git a/src/backend/catalog/pg_opfamily_d.h b/src/backend/catalog/pg_opfamily_d.h
new file mode 100644
index 0000000..353f686
--- /dev/null
+++ b/src/backend/catalog/pg_opfamily_d.h
@@ -0,0 +1,47 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_opfamily_d.h
+ * Macro definitions for pg_opfamily
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_OPFAMILY_D_H
+#define PG_OPFAMILY_D_H
+
+#define OperatorFamilyRelationId 2753
+
+#define Anum_pg_opfamily_oid 1
+#define Anum_pg_opfamily_opfmethod 2
+#define Anum_pg_opfamily_opfname 3
+#define Anum_pg_opfamily_opfnamespace 4
+#define Anum_pg_opfamily_opfowner 5
+
+#define Natts_pg_opfamily 5
+
+
+#define IsBooleanOpfamily(opfamily) \
+ ((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID)
+
+#define BOOL_BTREE_FAM_OID 424
+#define BPCHAR_BTREE_FAM_OID 426
+#define BYTEA_BTREE_FAM_OID 428
+#define NETWORK_BTREE_FAM_OID 1974
+#define INTEGER_BTREE_FAM_OID 1976
+#define OID_BTREE_FAM_OID 1989
+#define TEXT_BTREE_FAM_OID 1994
+#define TEXT_PATTERN_BTREE_FAM_OID 2095
+#define BPCHAR_PATTERN_BTREE_FAM_OID 2097
+#define BOOL_HASH_FAM_OID 2222
+#define TEXT_SPGIST_FAM_OID 4017
+
+#endif /* PG_OPFAMILY_D_H */
diff --git a/src/backend/catalog/pg_partitioned_table_d.h b/src/backend/catalog/pg_partitioned_table_d.h
new file mode 100644
index 0000000..cc27349
--- /dev/null
+++ b/src/backend/catalog/pg_partitioned_table_d.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_partitioned_table_d.h
+ * Macro definitions for pg_partitioned_table
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PARTITIONED_TABLE_D_H
+#define PG_PARTITIONED_TABLE_D_H
+
+#define PartitionedRelationId 3350
+
+#define Anum_pg_partitioned_table_partrelid 1
+#define Anum_pg_partitioned_table_partstrat 2
+#define Anum_pg_partitioned_table_partnatts 3
+#define Anum_pg_partitioned_table_partdefid 4
+#define Anum_pg_partitioned_table_partattrs 5
+#define Anum_pg_partitioned_table_partclass 6
+#define Anum_pg_partitioned_table_partcollation 7
+#define Anum_pg_partitioned_table_partexprs 8
+
+#define Natts_pg_partitioned_table 8
+
+
+#endif /* PG_PARTITIONED_TABLE_D_H */
diff --git a/src/backend/catalog/pg_policy_d.h b/src/backend/catalog/pg_policy_d.h
new file mode 100644
index 0000000..1d1dd56
--- /dev/null
+++ b/src/backend/catalog/pg_policy_d.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_policy_d.h
+ * Macro definitions for pg_policy
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_POLICY_D_H
+#define PG_POLICY_D_H
+
+#define PolicyRelationId 3256
+
+#define Anum_pg_policy_oid 1
+#define Anum_pg_policy_polname 2
+#define Anum_pg_policy_polrelid 3
+#define Anum_pg_policy_polcmd 4
+#define Anum_pg_policy_polpermissive 5
+#define Anum_pg_policy_polroles 6
+#define Anum_pg_policy_polqual 7
+#define Anum_pg_policy_polwithcheck 8
+
+#define Natts_pg_policy 8
+
+
+#endif /* PG_POLICY_D_H */
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
new file mode 100644
index 0000000..7c0a18d
--- /dev/null
+++ b/src/backend/catalog/pg_proc.c
@@ -0,0 +1,1157 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_proc.c
+ * routines to support manipulation of the pg_proc relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_proc.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "access/xact.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_language.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_transform.h"
+#include "catalog/pg_type.h"
+#include "commands/defrem.h"
+#include "executor/functions.h"
+#include "funcapi.h"
+#include "mb/pg_wchar.h"
+#include "miscadmin.h"
+#include "nodes/nodeFuncs.h"
+#include "parser/parse_coerce.h"
+#include "parser/parse_type.h"
+#include "tcop/pquery.h"
+#include "tcop/tcopprot.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/regproc.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+
+typedef struct
+{
+ char *proname;
+ char *prosrc;
+} parse_error_callback_arg;
+
+static void sql_function_parse_error_callback(void *arg);
+static int match_prosrc_to_query(const char *prosrc, const char *queryText,
+ int cursorpos);
+static bool match_prosrc_to_literal(const char *prosrc, const char *literal,
+ int cursorpos, int *newcursorpos);
+
+
+/* ----------------------------------------------------------------
+ * ProcedureCreate
+ *
+ * Note: allParameterTypes, parameterModes, parameterNames, trftypes, and proconfig
+ * are either arrays of the proper types or NULL. We declare them Datum,
+ * not "ArrayType *", to avoid importing array.h into pg_proc.h.
+ * ----------------------------------------------------------------
+ */
+ObjectAddress
+ProcedureCreate(const char *procedureName,
+ Oid procNamespace,
+ bool replace,
+ bool returnsSet,
+ Oid returnType,
+ Oid proowner,
+ Oid languageObjectId,
+ Oid languageValidator,
+ const char *prosrc,
+ const char *probin,
+ char prokind,
+ bool security_definer,
+ bool isLeakProof,
+ bool isStrict,
+ char volatility,
+ char parallel,
+ oidvector *parameterTypes,
+ Datum allParameterTypes,
+ Datum parameterModes,
+ Datum parameterNames,
+ List *parameterDefaults,
+ Datum trftypes,
+ Datum proconfig,
+ Oid prosupport,
+ float4 procost,
+ float4 prorows)
+{
+ Oid retval;
+ int parameterCount;
+ int allParamCount;
+ Oid *allParams;
+ char *paramModes = NULL;
+ Oid variadicType = InvalidOid;
+ Acl *proacl = NULL;
+ Relation rel;
+ HeapTuple tup;
+ HeapTuple oldtup;
+ bool nulls[Natts_pg_proc];
+ Datum values[Natts_pg_proc];
+ bool replaces[Natts_pg_proc];
+ NameData procname;
+ TupleDesc tupDesc;
+ bool is_update;
+ ObjectAddress myself,
+ referenced;
+ char *detailmsg;
+ int i;
+ Oid trfid;
+
+ /*
+ * sanity checks
+ */
+ Assert(PointerIsValid(prosrc));
+
+ parameterCount = parameterTypes->dim1;
+ if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS)
+ ereport(ERROR,
+ (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
+ errmsg_plural("functions cannot have more than %d argument",
+ "functions cannot have more than %d arguments",
+ FUNC_MAX_ARGS,
+ FUNC_MAX_ARGS)));
+ /* note: the above is correct, we do NOT count output arguments */
+
+ /* Deconstruct array inputs */
+ if (allParameterTypes != PointerGetDatum(NULL))
+ {
+ /*
+ * We expect the array to be a 1-D OID array; verify that. We don't
+ * need to use deconstruct_array() since the array data is just going
+ * to look like a C array of OID values.
+ */
+ ArrayType *allParamArray = (ArrayType *) DatumGetPointer(allParameterTypes);
+
+ allParamCount = ARR_DIMS(allParamArray)[0];
+ if (ARR_NDIM(allParamArray) != 1 ||
+ allParamCount <= 0 ||
+ ARR_HASNULL(allParamArray) ||
+ ARR_ELEMTYPE(allParamArray) != OIDOID)
+ elog(ERROR, "allParameterTypes is not a 1-D Oid array");
+ allParams = (Oid *) ARR_DATA_PTR(allParamArray);
+ Assert(allParamCount >= parameterCount);
+ /* we assume caller got the contents right */
+ }
+ else
+ {
+ allParamCount = parameterCount;
+ allParams = parameterTypes->values;
+ }
+
+ if (parameterModes != PointerGetDatum(NULL))
+ {
+ /*
+ * We expect the array to be a 1-D CHAR array; verify that. We don't
+ * need to use deconstruct_array() since the array data is just going
+ * to look like a C array of char values.
+ */
+ ArrayType *modesArray = (ArrayType *) DatumGetPointer(parameterModes);
+
+ if (ARR_NDIM(modesArray) != 1 ||
+ ARR_DIMS(modesArray)[0] != allParamCount ||
+ ARR_HASNULL(modesArray) ||
+ ARR_ELEMTYPE(modesArray) != CHAROID)
+ elog(ERROR, "parameterModes is not a 1-D char array");
+ paramModes = (char *) ARR_DATA_PTR(modesArray);
+ }
+
+ /*
+ * Do not allow polymorphic return type unless there is a polymorphic
+ * input argument that we can use to deduce the actual return type.
+ */
+ detailmsg = check_valid_polymorphic_signature(returnType,
+ parameterTypes->values,
+ parameterCount);
+ if (detailmsg)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("cannot determine result data type"),
+ errdetail_internal("%s", detailmsg)));
+
+ /*
+ * Also, do not allow return type INTERNAL unless at least one input
+ * argument is INTERNAL.
+ */
+ detailmsg = check_valid_internal_signature(returnType,
+ parameterTypes->values,
+ parameterCount);
+ if (detailmsg)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("unsafe use of pseudo-type \"internal\""),
+ errdetail_internal("%s", detailmsg)));
+
+ /*
+ * Apply the same tests to any OUT arguments.
+ */
+ if (allParameterTypes != PointerGetDatum(NULL))
+ {
+ for (i = 0; i < allParamCount; i++)
+ {
+ if (paramModes == NULL ||
+ paramModes[i] == PROARGMODE_IN ||
+ paramModes[i] == PROARGMODE_VARIADIC)
+ continue; /* ignore input-only params */
+
+ detailmsg = check_valid_polymorphic_signature(allParams[i],
+ parameterTypes->values,
+ parameterCount);
+ if (detailmsg)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("cannot determine result data type"),
+ errdetail_internal("%s", detailmsg)));
+ detailmsg = check_valid_internal_signature(allParams[i],
+ parameterTypes->values,
+ parameterCount);
+ if (detailmsg)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("unsafe use of pseudo-type \"internal\""),
+ errdetail_internal("%s", detailmsg)));
+ }
+ }
+
+ /* Identify variadic argument type, if any */
+ if (paramModes != NULL)
+ {
+ /*
+ * Only the last input parameter can be variadic; if it is, save its
+ * element type. Errors here are just elog since caller should have
+ * checked this already.
+ */
+ for (i = 0; i < allParamCount; i++)
+ {
+ switch (paramModes[i])
+ {
+ case PROARGMODE_IN:
+ case PROARGMODE_INOUT:
+ if (OidIsValid(variadicType))
+ elog(ERROR, "variadic parameter must be last");
+ break;
+ case PROARGMODE_OUT:
+ case PROARGMODE_TABLE:
+ /* okay */
+ break;
+ case PROARGMODE_VARIADIC:
+ if (OidIsValid(variadicType))
+ elog(ERROR, "variadic parameter must be last");
+ switch (allParams[i])
+ {
+ case ANYOID:
+ variadicType = ANYOID;
+ break;
+ case ANYARRAYOID:
+ variadicType = ANYELEMENTOID;
+ break;
+ case ANYCOMPATIBLEARRAYOID:
+ variadicType = ANYCOMPATIBLEOID;
+ break;
+ default:
+ variadicType = get_element_type(allParams[i]);
+ if (!OidIsValid(variadicType))
+ elog(ERROR, "variadic parameter is not an array");
+ break;
+ }
+ break;
+ default:
+ elog(ERROR, "invalid parameter mode '%c'", paramModes[i]);
+ break;
+ }
+ }
+ }
+
+ /*
+ * All seems OK; prepare the data to be inserted into pg_proc.
+ */
+
+ for (i = 0; i < Natts_pg_proc; ++i)
+ {
+ nulls[i] = false;
+ values[i] = (Datum) 0;
+ replaces[i] = true;
+ }
+
+ namestrcpy(&procname, procedureName);
+ values[Anum_pg_proc_proname - 1] = NameGetDatum(&procname);
+ values[Anum_pg_proc_pronamespace - 1] = ObjectIdGetDatum(procNamespace);
+ values[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(proowner);
+ values[Anum_pg_proc_prolang - 1] = ObjectIdGetDatum(languageObjectId);
+ values[Anum_pg_proc_procost - 1] = Float4GetDatum(procost);
+ values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows);
+ values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType);
+ values[Anum_pg_proc_prosupport - 1] = ObjectIdGetDatum(prosupport);
+ values[Anum_pg_proc_prokind - 1] = CharGetDatum(prokind);
+ values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer);
+ values[Anum_pg_proc_proleakproof - 1] = BoolGetDatum(isLeakProof);
+ values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict);
+ values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet);
+ values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility);
+ values[Anum_pg_proc_proparallel - 1] = CharGetDatum(parallel);
+ values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount);
+ values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults));
+ values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType);
+ values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes);
+ if (allParameterTypes != PointerGetDatum(NULL))
+ values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes;
+ else
+ nulls[Anum_pg_proc_proallargtypes - 1] = true;
+ if (parameterModes != PointerGetDatum(NULL))
+ values[Anum_pg_proc_proargmodes - 1] = parameterModes;
+ else
+ nulls[Anum_pg_proc_proargmodes - 1] = true;
+ if (parameterNames != PointerGetDatum(NULL))
+ values[Anum_pg_proc_proargnames - 1] = parameterNames;
+ else
+ nulls[Anum_pg_proc_proargnames - 1] = true;
+ if (parameterDefaults != NIL)
+ values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults));
+ else
+ nulls[Anum_pg_proc_proargdefaults - 1] = true;
+ if (trftypes != PointerGetDatum(NULL))
+ values[Anum_pg_proc_protrftypes - 1] = trftypes;
+ else
+ nulls[Anum_pg_proc_protrftypes - 1] = true;
+ values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc);
+ if (probin)
+ values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin);
+ else
+ nulls[Anum_pg_proc_probin - 1] = true;
+ if (proconfig != PointerGetDatum(NULL))
+ values[Anum_pg_proc_proconfig - 1] = proconfig;
+ else
+ nulls[Anum_pg_proc_proconfig - 1] = true;
+ /* proacl will be determined later */
+
+ rel = table_open(ProcedureRelationId, RowExclusiveLock);
+ tupDesc = RelationGetDescr(rel);
+
+ /* Check for pre-existing definition */
+ oldtup = SearchSysCache3(PROCNAMEARGSNSP,
+ PointerGetDatum(procedureName),
+ PointerGetDatum(parameterTypes),
+ ObjectIdGetDatum(procNamespace));
+
+ if (HeapTupleIsValid(oldtup))
+ {
+ /* There is one; okay to replace it? */
+ Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup);
+ Datum proargnames;
+ bool isnull;
+ const char *dropcmd;
+
+ if (!replace)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_FUNCTION),
+ errmsg("function \"%s\" already exists with same argument types",
+ procedureName)));
+ if (!pg_proc_ownercheck(oldproc->oid, proowner))
+ aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
+ procedureName);
+
+ /* Not okay to change routine kind */
+ if (oldproc->prokind != prokind)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot change routine kind"),
+ (oldproc->prokind == PROKIND_AGGREGATE ?
+ errdetail("\"%s\" is an aggregate function.", procedureName) :
+ oldproc->prokind == PROKIND_FUNCTION ?
+ errdetail("\"%s\" is a function.", procedureName) :
+ oldproc->prokind == PROKIND_PROCEDURE ?
+ errdetail("\"%s\" is a procedure.", procedureName) :
+ oldproc->prokind == PROKIND_WINDOW ?
+ errdetail("\"%s\" is a window function.", procedureName) :
+ 0)));
+
+ dropcmd = (prokind == PROKIND_PROCEDURE ? "DROP PROCEDURE" :
+ prokind == PROKIND_AGGREGATE ? "DROP AGGREGATE" :
+ "DROP FUNCTION");
+
+ /*
+ * Not okay to change the return type of the existing proc, since
+ * existing rules, views, etc may depend on the return type.
+ *
+ * In case of a procedure, a changing return type means that whether
+ * the procedure has output parameters was changed. Since there is no
+ * user visible return type, we produce a more specific error message.
+ */
+ if (returnType != oldproc->prorettype ||
+ returnsSet != oldproc->proretset)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ prokind == PROKIND_PROCEDURE
+ ? errmsg("cannot change whether a procedure has output parameters")
+ : errmsg("cannot change return type of existing function"),
+
+ /*
+ * translator: first %s is DROP FUNCTION, DROP PROCEDURE, or DROP
+ * AGGREGATE
+ */
+ errhint("Use %s %s first.",
+ dropcmd,
+ format_procedure(oldproc->oid))));
+
+ /*
+ * If it returns RECORD, check for possible change of record type
+ * implied by OUT parameters
+ */
+ if (returnType == RECORDOID)
+ {
+ TupleDesc olddesc;
+ TupleDesc newdesc;
+
+ olddesc = build_function_result_tupdesc_t(oldtup);
+ newdesc = build_function_result_tupdesc_d(prokind,
+ allParameterTypes,
+ parameterModes,
+ parameterNames);
+ if (olddesc == NULL && newdesc == NULL)
+ /* ok, both are runtime-defined RECORDs */ ;
+ else if (olddesc == NULL || newdesc == NULL ||
+ !equalTupleDescs(olddesc, newdesc))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("cannot change return type of existing function"),
+ errdetail("Row type defined by OUT parameters is different."),
+ /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
+ errhint("Use %s %s first.",
+ dropcmd,
+ format_procedure(oldproc->oid))));
+ }
+
+ /*
+ * If there were any named input parameters, check to make sure the
+ * names have not been changed, as this could break existing calls. We
+ * allow adding names to formerly unnamed parameters, though.
+ */
+ proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
+ Anum_pg_proc_proargnames,
+ &isnull);
+ if (!isnull)
+ {
+ Datum proargmodes;
+ char **old_arg_names;
+ char **new_arg_names;
+ int n_old_arg_names;
+ int n_new_arg_names;
+ int j;
+
+ proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
+ Anum_pg_proc_proargmodes,
+ &isnull);
+ if (isnull)
+ proargmodes = PointerGetDatum(NULL); /* just to be sure */
+
+ n_old_arg_names = get_func_input_arg_names(proargnames,
+ proargmodes,
+ &old_arg_names);
+ n_new_arg_names = get_func_input_arg_names(parameterNames,
+ parameterModes,
+ &new_arg_names);
+ for (j = 0; j < n_old_arg_names; j++)
+ {
+ if (old_arg_names[j] == NULL)
+ continue;
+ if (j >= n_new_arg_names || new_arg_names[j] == NULL ||
+ strcmp(old_arg_names[j], new_arg_names[j]) != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("cannot change name of input parameter \"%s\"",
+ old_arg_names[j]),
+ /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
+ errhint("Use %s %s first.",
+ dropcmd,
+ format_procedure(oldproc->oid))));
+ }
+ }
+
+ /*
+ * If there are existing defaults, check compatibility: redefinition
+ * must not remove any defaults nor change their types. (Removing a
+ * default might cause a function to fail to satisfy an existing call.
+ * Changing type would only be possible if the associated parameter is
+ * polymorphic, and in such cases a change of default type might alter
+ * the resolved output type of existing calls.)
+ */
+ if (oldproc->pronargdefaults != 0)
+ {
+ Datum proargdefaults;
+ List *oldDefaults;
+ ListCell *oldlc;
+ ListCell *newlc;
+
+ if (list_length(parameterDefaults) < oldproc->pronargdefaults)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("cannot remove parameter defaults from existing function"),
+ /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
+ errhint("Use %s %s first.",
+ dropcmd,
+ format_procedure(oldproc->oid))));
+
+ proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
+ Anum_pg_proc_proargdefaults,
+ &isnull);
+ Assert(!isnull);
+ oldDefaults = castNode(List, stringToNode(TextDatumGetCString(proargdefaults)));
+ Assert(list_length(oldDefaults) == oldproc->pronargdefaults);
+
+ /* new list can have more defaults than old, advance over 'em */
+ newlc = list_nth_cell(parameterDefaults,
+ list_length(parameterDefaults) -
+ oldproc->pronargdefaults);
+
+ foreach(oldlc, oldDefaults)
+ {
+ Node *oldDef = (Node *) lfirst(oldlc);
+ Node *newDef = (Node *) lfirst(newlc);
+
+ if (exprType(oldDef) != exprType(newDef))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("cannot change data type of existing parameter default value"),
+ /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
+ errhint("Use %s %s first.",
+ dropcmd,
+ format_procedure(oldproc->oid))));
+ newlc = lnext(parameterDefaults, newlc);
+ }
+ }
+
+ /*
+ * Do not change existing oid, ownership or permissions, either. Note
+ * dependency-update code below has to agree with this decision.
+ */
+ replaces[Anum_pg_proc_oid - 1] = false;
+ replaces[Anum_pg_proc_proowner - 1] = false;
+ replaces[Anum_pg_proc_proacl - 1] = false;
+
+ /* Okay, do it... */
+ tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ ReleaseSysCache(oldtup);
+ is_update = true;
+ }
+ else
+ {
+ /* Creating a new procedure */
+ Oid newOid;
+
+ /* First, get default permissions and set up proacl */
+ proacl = get_user_default_acl(OBJECT_FUNCTION, proowner,
+ procNamespace);
+ if (proacl != NULL)
+ values[Anum_pg_proc_proacl - 1] = PointerGetDatum(proacl);
+ else
+ nulls[Anum_pg_proc_proacl - 1] = true;
+
+ newOid = GetNewOidWithIndex(rel, ProcedureOidIndexId,
+ Anum_pg_proc_oid);
+ values[Anum_pg_proc_oid - 1] = ObjectIdGetDatum(newOid);
+ tup = heap_form_tuple(tupDesc, values, nulls);
+ CatalogTupleInsert(rel, tup);
+ is_update = false;
+ }
+
+
+ retval = ((Form_pg_proc) GETSTRUCT(tup))->oid;
+
+ /*
+ * Create dependencies for the new function. If we are updating an
+ * existing function, first delete any existing pg_depend entries.
+ * (However, since we are not changing ownership or permissions, the
+ * shared dependencies do *not* need to change, and we leave them alone.)
+ */
+ if (is_update)
+ deleteDependencyRecordsFor(ProcedureRelationId, retval, true);
+
+ myself.classId = ProcedureRelationId;
+ myself.objectId = retval;
+ myself.objectSubId = 0;
+
+ /* dependency on namespace */
+ referenced.classId = NamespaceRelationId;
+ referenced.objectId = procNamespace;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* dependency on implementation language */
+ referenced.classId = LanguageRelationId;
+ referenced.objectId = languageObjectId;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* dependency on return type */
+ referenced.classId = TypeRelationId;
+ referenced.objectId = returnType;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* dependency on transform used by return type, if any */
+ if ((trfid = get_transform_oid(returnType, languageObjectId, true)))
+ {
+ referenced.classId = TransformRelationId;
+ referenced.objectId = trfid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* dependency on parameter types */
+ for (i = 0; i < allParamCount; i++)
+ {
+ referenced.classId = TypeRelationId;
+ referenced.objectId = allParams[i];
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* dependency on transform used by parameter type, if any */
+ if ((trfid = get_transform_oid(allParams[i], languageObjectId, true)))
+ {
+ referenced.classId = TransformRelationId;
+ referenced.objectId = trfid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+ }
+
+ /* dependency on parameter default expressions */
+ if (parameterDefaults)
+ recordDependencyOnExpr(&myself, (Node *) parameterDefaults,
+ NIL, DEPENDENCY_NORMAL);
+
+ /* dependency on support function, if any */
+ if (OidIsValid(prosupport))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = prosupport;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* dependency on owner */
+ if (!is_update)
+ recordDependencyOnOwner(ProcedureRelationId, retval, proowner);
+
+ /* dependency on any roles mentioned in ACL */
+ if (!is_update)
+ recordDependencyOnNewAcl(ProcedureRelationId, retval, 0,
+ proowner, proacl);
+
+ /* dependency on extension */
+ recordDependencyOnCurrentExtension(&myself, is_update);
+
+ heap_freetuple(tup);
+
+ /* Post creation hook for new function */
+ InvokeObjectPostCreateHook(ProcedureRelationId, retval, 0);
+
+ table_close(rel, RowExclusiveLock);
+
+ /* Verify function body */
+ if (OidIsValid(languageValidator))
+ {
+ ArrayType *set_items = NULL;
+ int save_nestlevel = 0;
+
+ /* Advance command counter so new tuple can be seen by validator */
+ CommandCounterIncrement();
+
+ /*
+ * Set per-function configuration parameters so that the validation is
+ * done with the environment the function expects. However, if
+ * check_function_bodies is off, we don't do this, because that would
+ * create dump ordering hazards that pg_dump doesn't know how to deal
+ * with. (For example, a SET clause might refer to a not-yet-created
+ * text search configuration.) This means that the validator
+ * shouldn't complain about anything that might depend on a GUC
+ * parameter when check_function_bodies is off.
+ */
+ if (check_function_bodies)
+ {
+ set_items = (ArrayType *) DatumGetPointer(proconfig);
+ if (set_items) /* Need a new GUC nesting level */
+ {
+ save_nestlevel = NewGUCNestLevel();
+ ProcessGUCArray(set_items,
+ (superuser() ? PGC_SUSET : PGC_USERSET),
+ PGC_S_SESSION,
+ GUC_ACTION_SAVE);
+ }
+ }
+
+ OidFunctionCall1(languageValidator, ObjectIdGetDatum(retval));
+
+ if (set_items)
+ AtEOXact_GUC(true, save_nestlevel);
+ }
+
+ return myself;
+}
+
+
+
+/*
+ * Validator for internal functions
+ *
+ * Check that the given internal function name (the "prosrc" value) is
+ * a known builtin function.
+ */
+Datum
+fmgr_internal_validator(PG_FUNCTION_ARGS)
+{
+ Oid funcoid = PG_GETARG_OID(0);
+ HeapTuple tuple;
+ bool isnull;
+ Datum tmp;
+ char *prosrc;
+
+ if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
+ PG_RETURN_VOID();
+
+ /*
+ * We do not honor check_function_bodies since it's unlikely the function
+ * name will be found later if it isn't there now.
+ */
+
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", funcoid);
+
+ tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
+ if (isnull)
+ elog(ERROR, "null prosrc");
+ prosrc = TextDatumGetCString(tmp);
+
+ if (fmgr_internal_function(prosrc) == InvalidOid)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("there is no built-in function named \"%s\"",
+ prosrc)));
+
+ ReleaseSysCache(tuple);
+
+ PG_RETURN_VOID();
+}
+
+
+
+/*
+ * Validator for C language functions
+ *
+ * Make sure that the library file exists, is loadable, and contains
+ * the specified link symbol. Also check for a valid function
+ * information record.
+ */
+Datum
+fmgr_c_validator(PG_FUNCTION_ARGS)
+{
+ Oid funcoid = PG_GETARG_OID(0);
+ void *libraryhandle;
+ HeapTuple tuple;
+ bool isnull;
+ Datum tmp;
+ char *prosrc;
+ char *probin;
+
+ if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
+ PG_RETURN_VOID();
+
+ /*
+ * It'd be most consistent to skip the check if !check_function_bodies,
+ * but the purpose of that switch is to be helpful for pg_dump loading,
+ * and for pg_dump loading it's much better if we *do* check.
+ */
+
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", funcoid);
+
+ tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
+ if (isnull)
+ elog(ERROR, "null prosrc for C function %u", funcoid);
+ prosrc = TextDatumGetCString(tmp);
+
+ tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_probin, &isnull);
+ if (isnull)
+ elog(ERROR, "null probin for C function %u", funcoid);
+ probin = TextDatumGetCString(tmp);
+
+ (void) load_external_function(probin, prosrc, true, &libraryhandle);
+ (void) fetch_finfo_record(libraryhandle, prosrc);
+
+ ReleaseSysCache(tuple);
+
+ PG_RETURN_VOID();
+}
+
+
+/*
+ * Validator for SQL language functions
+ *
+ * Parse it here in order to be sure that it contains no syntax errors.
+ */
+Datum
+fmgr_sql_validator(PG_FUNCTION_ARGS)
+{
+ Oid funcoid = PG_GETARG_OID(0);
+ HeapTuple tuple;
+ Form_pg_proc proc;
+ List *raw_parsetree_list;
+ List *querytree_list;
+ ListCell *lc;
+ bool isnull;
+ Datum tmp;
+ char *prosrc;
+ parse_error_callback_arg callback_arg;
+ ErrorContextCallback sqlerrcontext;
+ bool haspolyarg;
+ int i;
+
+ if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
+ PG_RETURN_VOID();
+
+ tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for function %u", funcoid);
+ proc = (Form_pg_proc) GETSTRUCT(tuple);
+
+ /* Disallow pseudotype result */
+ /* except for RECORD, VOID, or polymorphic */
+ if (get_typtype(proc->prorettype) == TYPTYPE_PSEUDO &&
+ proc->prorettype != RECORDOID &&
+ proc->prorettype != VOIDOID &&
+ !IsPolymorphicType(proc->prorettype))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("SQL functions cannot return type %s",
+ format_type_be(proc->prorettype))));
+
+ /* Disallow pseudotypes in arguments */
+ /* except for polymorphic */
+ haspolyarg = false;
+ for (i = 0; i < proc->pronargs; i++)
+ {
+ if (get_typtype(proc->proargtypes.values[i]) == TYPTYPE_PSEUDO)
+ {
+ if (IsPolymorphicType(proc->proargtypes.values[i]))
+ haspolyarg = true;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+ errmsg("SQL functions cannot have arguments of type %s",
+ format_type_be(proc->proargtypes.values[i]))));
+ }
+ }
+
+ /* Postpone body checks if !check_function_bodies */
+ if (check_function_bodies)
+ {
+ tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
+ if (isnull)
+ elog(ERROR, "null prosrc");
+
+ prosrc = TextDatumGetCString(tmp);
+
+ /*
+ * Setup error traceback support for ereport().
+ */
+ callback_arg.proname = NameStr(proc->proname);
+ callback_arg.prosrc = prosrc;
+
+ sqlerrcontext.callback = sql_function_parse_error_callback;
+ sqlerrcontext.arg = (void *) &callback_arg;
+ sqlerrcontext.previous = error_context_stack;
+ error_context_stack = &sqlerrcontext;
+
+ /*
+ * We can't do full prechecking of the function definition if there
+ * are any polymorphic input types, because actual datatypes of
+ * expression results will be unresolvable. The check will be done at
+ * runtime instead.
+ *
+ * We can run the text through the raw parser though; this will at
+ * least catch silly syntactic errors.
+ */
+ raw_parsetree_list = pg_parse_query(prosrc);
+
+ if (!haspolyarg)
+ {
+ /*
+ * OK to do full precheck: analyze and rewrite the queries, then
+ * verify the result type.
+ */
+ SQLFunctionParseInfoPtr pinfo;
+ Oid rettype;
+ TupleDesc rettupdesc;
+
+ /* But first, set up parameter information */
+ pinfo = prepare_sql_fn_parse_info(tuple, NULL, InvalidOid);
+
+ querytree_list = NIL;
+ foreach(lc, raw_parsetree_list)
+ {
+ RawStmt *parsetree = lfirst_node(RawStmt, lc);
+ List *querytree_sublist;
+
+ querytree_sublist = pg_analyze_and_rewrite_params(parsetree,
+ prosrc,
+ (ParserSetupHook) sql_fn_parser_setup,
+ pinfo,
+ NULL);
+ querytree_list = lappend(querytree_list,
+ querytree_sublist);
+ }
+
+ check_sql_fn_statements(querytree_list);
+
+ (void) get_func_result_type(funcoid, &rettype, &rettupdesc);
+
+ (void) check_sql_fn_retval(querytree_list,
+ rettype, rettupdesc,
+ false, NULL);
+ }
+
+ error_context_stack = sqlerrcontext.previous;
+ }
+
+ ReleaseSysCache(tuple);
+
+ PG_RETURN_VOID();
+}
+
+/*
+ * Error context callback for handling errors in SQL function definitions
+ */
+static void
+sql_function_parse_error_callback(void *arg)
+{
+ parse_error_callback_arg *callback_arg = (parse_error_callback_arg *) arg;
+
+ /* See if it's a syntax error; if so, transpose to CREATE FUNCTION */
+ if (!function_parse_error_transpose(callback_arg->prosrc))
+ {
+ /* If it's not a syntax error, push info onto context stack */
+ errcontext("SQL function \"%s\"", callback_arg->proname);
+ }
+}
+
+/*
+ * Adjust a syntax error occurring inside the function body of a CREATE
+ * FUNCTION or DO command. This can be used by any function validator or
+ * anonymous-block handler, not only for SQL-language functions.
+ * It is assumed that the syntax error position is initially relative to the
+ * function body string (as passed in). If possible, we adjust the position
+ * to reference the original command text; if we can't manage that, we set
+ * up an "internal query" syntax error instead.
+ *
+ * Returns true if a syntax error was processed, false if not.
+ */
+bool
+function_parse_error_transpose(const char *prosrc)
+{
+ int origerrposition;
+ int newerrposition;
+ const char *queryText;
+
+ /*
+ * Nothing to do unless we are dealing with a syntax error that has a
+ * cursor position.
+ *
+ * Some PLs may prefer to report the error position as an internal error
+ * to begin with, so check that too.
+ */
+ origerrposition = geterrposition();
+ if (origerrposition <= 0)
+ {
+ origerrposition = getinternalerrposition();
+ if (origerrposition <= 0)
+ return false;
+ }
+
+ /* We can get the original query text from the active portal (hack...) */
+ Assert(ActivePortal && ActivePortal->status == PORTAL_ACTIVE);
+ queryText = ActivePortal->sourceText;
+
+ /* Try to locate the prosrc in the original text */
+ newerrposition = match_prosrc_to_query(prosrc, queryText, origerrposition);
+
+ if (newerrposition > 0)
+ {
+ /* Successful, so fix error position to reference original query */
+ errposition(newerrposition);
+ /* Get rid of any report of the error as an "internal query" */
+ internalerrposition(0);
+ internalerrquery(NULL);
+ }
+ else
+ {
+ /*
+ * If unsuccessful, convert the position to an internal position
+ * marker and give the function text as the internal query.
+ */
+ errposition(0);
+ internalerrposition(origerrposition);
+ internalerrquery(prosrc);
+ }
+
+ return true;
+}
+
+/*
+ * Try to locate the string literal containing the function body in the
+ * given text of the CREATE FUNCTION or DO command. If successful, return
+ * the character (not byte) index within the command corresponding to the
+ * given character index within the literal. If not successful, return 0.
+ */
+static int
+match_prosrc_to_query(const char *prosrc, const char *queryText,
+ int cursorpos)
+{
+ /*
+ * Rather than fully parsing the original command, we just scan the
+ * command looking for $prosrc$ or 'prosrc'. This could be fooled (though
+ * not in any very probable scenarios), so fail if we find more than one
+ * match.
+ */
+ int prosrclen = strlen(prosrc);
+ int querylen = strlen(queryText);
+ int matchpos = 0;
+ int curpos;
+ int newcursorpos;
+
+ for (curpos = 0; curpos < querylen - prosrclen; curpos++)
+ {
+ if (queryText[curpos] == '$' &&
+ strncmp(prosrc, &queryText[curpos + 1], prosrclen) == 0 &&
+ queryText[curpos + 1 + prosrclen] == '$')
+ {
+ /*
+ * Found a $foo$ match. Since there are no embedded quoting
+ * characters in a dollar-quoted literal, we don't have to do any
+ * fancy arithmetic; just offset by the starting position.
+ */
+ if (matchpos)
+ return 0; /* multiple matches, fail */
+ matchpos = pg_mbstrlen_with_len(queryText, curpos + 1)
+ + cursorpos;
+ }
+ else if (queryText[curpos] == '\'' &&
+ match_prosrc_to_literal(prosrc, &queryText[curpos + 1],
+ cursorpos, &newcursorpos))
+ {
+ /*
+ * Found a 'foo' match. match_prosrc_to_literal() has adjusted
+ * for any quotes or backslashes embedded in the literal.
+ */
+ if (matchpos)
+ return 0; /* multiple matches, fail */
+ matchpos = pg_mbstrlen_with_len(queryText, curpos + 1)
+ + newcursorpos;
+ }
+ }
+
+ return matchpos;
+}
+
+/*
+ * Try to match the given source text to a single-quoted literal.
+ * If successful, adjust newcursorpos to correspond to the character
+ * (not byte) index corresponding to cursorpos in the source text.
+ *
+ * At entry, literal points just past a ' character. We must check for the
+ * trailing quote.
+ */
+static bool
+match_prosrc_to_literal(const char *prosrc, const char *literal,
+ int cursorpos, int *newcursorpos)
+{
+ int newcp = cursorpos;
+ int chlen;
+
+ /*
+ * This implementation handles backslashes and doubled quotes in the
+ * string literal. It does not handle the SQL syntax for literals
+ * continued across line boundaries.
+ *
+ * We do the comparison a character at a time, not a byte at a time, so
+ * that we can do the correct cursorpos math.
+ */
+ while (*prosrc)
+ {
+ cursorpos--; /* characters left before cursor */
+
+ /*
+ * Check for backslashes and doubled quotes in the literal; adjust
+ * newcp when one is found before the cursor.
+ */
+ if (*literal == '\\')
+ {
+ literal++;
+ if (cursorpos > 0)
+ newcp++;
+ }
+ else if (*literal == '\'')
+ {
+ if (literal[1] != '\'')
+ goto fail;
+ literal++;
+ if (cursorpos > 0)
+ newcp++;
+ }
+ chlen = pg_mblen(prosrc);
+ if (strncmp(prosrc, literal, chlen) != 0)
+ goto fail;
+ prosrc += chlen;
+ literal += chlen;
+ }
+
+ if (*literal == '\'' && literal[1] != '\'')
+ {
+ /* success */
+ *newcursorpos = newcp;
+ return true;
+ }
+
+fail:
+ /* Must set *newcursorpos to suppress compiler warning */
+ *newcursorpos = newcp;
+ return false;
+}
+
+List *
+oid_array_to_list(Datum datum)
+{
+ ArrayType *array = DatumGetArrayTypeP(datum);
+ Datum *values;
+ int nelems;
+ int i;
+ List *result = NIL;
+
+ deconstruct_array(array,
+ OIDOID,
+ sizeof(Oid), true, TYPALIGN_INT,
+ &values, NULL, &nelems);
+ for (i = 0; i < nelems; i++)
+ result = lappend_oid(result, values[i]);
+ return result;
+}
diff --git a/src/backend/catalog/pg_proc_d.h b/src/backend/catalog/pg_proc_d.h
new file mode 100644
index 0000000..973c779
--- /dev/null
+++ b/src/backend/catalog/pg_proc_d.h
@@ -0,0 +1,99 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_proc_d.h
+ * Macro definitions for pg_proc
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PROC_D_H
+#define PG_PROC_D_H
+
+#define ProcedureRelationId 1255
+#define ProcedureRelation_Rowtype_Id 81
+
+#define Anum_pg_proc_oid 1
+#define Anum_pg_proc_proname 2
+#define Anum_pg_proc_pronamespace 3
+#define Anum_pg_proc_proowner 4
+#define Anum_pg_proc_prolang 5
+#define Anum_pg_proc_procost 6
+#define Anum_pg_proc_prorows 7
+#define Anum_pg_proc_provariadic 8
+#define Anum_pg_proc_prosupport 9
+#define Anum_pg_proc_prokind 10
+#define Anum_pg_proc_prosecdef 11
+#define Anum_pg_proc_proleakproof 12
+#define Anum_pg_proc_proisstrict 13
+#define Anum_pg_proc_proretset 14
+#define Anum_pg_proc_provolatile 15
+#define Anum_pg_proc_proparallel 16
+#define Anum_pg_proc_pronargs 17
+#define Anum_pg_proc_pronargdefaults 18
+#define Anum_pg_proc_prorettype 19
+#define Anum_pg_proc_proargtypes 20
+#define Anum_pg_proc_proallargtypes 21
+#define Anum_pg_proc_proargmodes 22
+#define Anum_pg_proc_proargnames 23
+#define Anum_pg_proc_proargdefaults 24
+#define Anum_pg_proc_protrftypes 25
+#define Anum_pg_proc_prosrc 26
+#define Anum_pg_proc_probin 27
+#define Anum_pg_proc_proconfig 28
+#define Anum_pg_proc_proacl 29
+
+#define Natts_pg_proc 29
+
+
+/*
+ * Symbolic values for prokind column
+ */
+#define PROKIND_FUNCTION 'f'
+#define PROKIND_AGGREGATE 'a'
+#define PROKIND_WINDOW 'w'
+#define PROKIND_PROCEDURE 'p'
+
+/*
+ * Symbolic values for provolatile column: these indicate whether the result
+ * of a function is dependent *only* on the values of its explicit arguments,
+ * or can change due to outside factors (such as parameter variables or
+ * table contents). NOTE: functions having side-effects, such as setval(),
+ * must be labeled volatile to ensure they will not get optimized away,
+ * even if the actual return value is not changeable.
+ */
+#define PROVOLATILE_IMMUTABLE 'i' /* never changes for given input */
+#define PROVOLATILE_STABLE 's' /* does not change within a scan */
+#define PROVOLATILE_VOLATILE 'v' /* can change even within a scan */
+
+/*
+ * Symbolic values for proparallel column: these indicate whether a function
+ * can be safely be run in a parallel backend, during parallelism but
+ * necessarily in the master, or only in non-parallel mode.
+ */
+#define PROPARALLEL_SAFE 's' /* can run in worker or master */
+#define PROPARALLEL_RESTRICTED 'r' /* can run in parallel master only */
+#define PROPARALLEL_UNSAFE 'u' /* banned while in parallel mode */
+
+/*
+ * Symbolic values for proargmodes column. Note that these must agree with
+ * the FunctionParameterMode enum in parsenodes.h; we declare them here to
+ * be accessible from either header.
+ */
+#define PROARGMODE_IN 'i'
+#define PROARGMODE_OUT 'o'
+#define PROARGMODE_INOUT 'b'
+#define PROARGMODE_VARIADIC 'v'
+#define PROARGMODE_TABLE 't'
+
+#define HEAP_TABLE_AM_HANDLER_OID 3
+
+#endif /* PG_PROC_D_H */
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
new file mode 100644
index 0000000..61bed1d
--- /dev/null
+++ b/src/backend/catalog/pg_publication.c
@@ -0,0 +1,557 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_publication.c
+ * publication C API manipulation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * pg_publication.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/tableam.h"
+#include "access/xact.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/index.h"
+#include "catalog/indexing.h"
+#include "catalog/namespace.h"
+#include "catalog/partition.h"
+#include "catalog/objectaccess.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_publication.h"
+#include "catalog/pg_publication_rel.h"
+#include "catalog/pg_type.h"
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/catcache.h"
+#include "utils/fmgroids.h"
+#include "utils/inval.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+/*
+ * Check if relation can be in given publication and throws appropriate
+ * error if not.
+ */
+static void
+check_publication_add_relation(Relation targetrel)
+{
+ /* Must be a regular or partitioned table */
+ if (RelationGetForm(targetrel)->relkind != RELKIND_RELATION &&
+ RelationGetForm(targetrel)->relkind != RELKIND_PARTITIONED_TABLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("\"%s\" is not a table",
+ RelationGetRelationName(targetrel)),
+ errdetail("Only tables can be added to publications.")));
+
+ /* Can't be system table */
+ if (IsCatalogRelation(targetrel))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("\"%s\" is a system table",
+ RelationGetRelationName(targetrel)),
+ errdetail("System tables cannot be added to publications.")));
+
+ /* UNLOGGED and TEMP relations cannot be part of publication. */
+ if (targetrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("table \"%s\" cannot be replicated",
+ RelationGetRelationName(targetrel)),
+ errdetail("Temporary and unlogged relations cannot be replicated.")));
+}
+
+/*
+ * Returns if relation represented by oid and Form_pg_class entry
+ * is publishable.
+ *
+ * Does same checks as the above, but does not need relation to be opened
+ * and also does not throw errors.
+ *
+ * XXX This also excludes all tables with relid < FirstNormalObjectId,
+ * ie all tables created during initdb. This mainly affects the preinstalled
+ * information_schema. IsCatalogRelationOid() only excludes tables with
+ * relid < FirstBootstrapObjectId, making that test rather redundant,
+ * but really we should get rid of the FirstNormalObjectId test not
+ * IsCatalogRelationOid. We can't do so today because we don't want
+ * information_schema tables to be considered publishable; but this test
+ * is really inadequate for that, since the information_schema could be
+ * dropped and reloaded and then it'll be considered publishable. The best
+ * long-term solution may be to add a "relispublishable" bool to pg_class,
+ * and depend on that instead of OID checks.
+ */
+static bool
+is_publishable_class(Oid relid, Form_pg_class reltuple)
+{
+ return (reltuple->relkind == RELKIND_RELATION ||
+ reltuple->relkind == RELKIND_PARTITIONED_TABLE) &&
+ !IsCatalogRelationOid(relid) &&
+ reltuple->relpersistence == RELPERSISTENCE_PERMANENT &&
+ relid >= FirstNormalObjectId;
+}
+
+/*
+ * Another variant of this, taking a Relation.
+ */
+bool
+is_publishable_relation(Relation rel)
+{
+ return is_publishable_class(RelationGetRelid(rel), rel->rd_rel);
+}
+
+
+/*
+ * SQL-callable variant of the above
+ *
+ * This returns null when the relation does not exist. This is intended to be
+ * used for example in psql to avoid gratuitous errors when there are
+ * concurrent catalog changes.
+ */
+Datum
+pg_relation_is_publishable(PG_FUNCTION_ARGS)
+{
+ Oid relid = PG_GETARG_OID(0);
+ HeapTuple tuple;
+ bool result;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ PG_RETURN_NULL();
+ result = is_publishable_class(relid, (Form_pg_class) GETSTRUCT(tuple));
+ ReleaseSysCache(tuple);
+ PG_RETURN_BOOL(result);
+}
+
+
+/*
+ * Insert new publication / relation mapping.
+ */
+ObjectAddress
+publication_add_relation(Oid pubid, Relation targetrel,
+ bool if_not_exists)
+{
+ Relation rel;
+ HeapTuple tup;
+ Datum values[Natts_pg_publication_rel];
+ bool nulls[Natts_pg_publication_rel];
+ Oid relid = RelationGetRelid(targetrel);
+ Oid prrelid;
+ Publication *pub = GetPublication(pubid);
+ ObjectAddress myself,
+ referenced;
+
+ rel = table_open(PublicationRelRelationId, RowExclusiveLock);
+
+ /*
+ * Check for duplicates. Note that this does not really prevent
+ * duplicates, it's here just to provide nicer error message in common
+ * case. The real protection is the unique key on the catalog.
+ */
+ if (SearchSysCacheExists2(PUBLICATIONRELMAP, ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(pubid)))
+ {
+ table_close(rel, RowExclusiveLock);
+
+ if (if_not_exists)
+ return InvalidObjectAddress;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("relation \"%s\" is already member of publication \"%s\"",
+ RelationGetRelationName(targetrel), pub->name)));
+ }
+
+ check_publication_add_relation(targetrel);
+
+ /* Form a tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+
+ prrelid = GetNewOidWithIndex(rel, PublicationRelObjectIndexId,
+ Anum_pg_publication_rel_oid);
+ values[Anum_pg_publication_rel_oid - 1] = ObjectIdGetDatum(prrelid);
+ values[Anum_pg_publication_rel_prpubid - 1] =
+ ObjectIdGetDatum(pubid);
+ values[Anum_pg_publication_rel_prrelid - 1] =
+ ObjectIdGetDatum(relid);
+
+ tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+
+ /* Insert tuple into catalog. */
+ CatalogTupleInsert(rel, tup);
+ heap_freetuple(tup);
+
+ ObjectAddressSet(myself, PublicationRelRelationId, prrelid);
+
+ /* Add dependency on the publication */
+ ObjectAddressSet(referenced, PublicationRelationId, pubid);
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+
+ /* Add dependency on the relation */
+ ObjectAddressSet(referenced, RelationRelationId, relid);
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+
+ /* Close the table. */
+ table_close(rel, RowExclusiveLock);
+
+ /* Invalidate relcache so that publication info is rebuilt. */
+ CacheInvalidateRelcache(targetrel);
+
+ return myself;
+}
+
+/* Gets list of publication oids for a relation */
+List *
+GetRelationPublications(Oid relid)
+{
+ List *result = NIL;
+ CatCList *pubrellist;
+ int i;
+
+ /* Find all publications associated with the relation. */
+ pubrellist = SearchSysCacheList1(PUBLICATIONRELMAP,
+ ObjectIdGetDatum(relid));
+ for (i = 0; i < pubrellist->n_members; i++)
+ {
+ HeapTuple tup = &pubrellist->members[i]->tuple;
+ Oid pubid = ((Form_pg_publication_rel) GETSTRUCT(tup))->prpubid;
+
+ result = lappend_oid(result, pubid);
+ }
+
+ ReleaseSysCacheList(pubrellist);
+
+ return result;
+}
+
+/*
+ * Gets list of relation oids for a publication.
+ *
+ * This should only be used for normal publications, the FOR ALL TABLES
+ * should use GetAllTablesPublicationRelations().
+ */
+List *
+GetPublicationRelations(Oid pubid, PublicationPartOpt pub_partopt)
+{
+ List *result;
+ Relation pubrelsrel;
+ ScanKeyData scankey;
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Find all publications associated with the relation. */
+ pubrelsrel = table_open(PublicationRelRelationId, AccessShareLock);
+
+ ScanKeyInit(&scankey,
+ Anum_pg_publication_rel_prpubid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(pubid));
+
+ scan = systable_beginscan(pubrelsrel, PublicationRelPrrelidPrpubidIndexId,
+ true, NULL, 1, &scankey);
+
+ result = NIL;
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_publication_rel pubrel;
+
+ pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+
+ if (get_rel_relkind(pubrel->prrelid) == RELKIND_PARTITIONED_TABLE &&
+ pub_partopt != PUBLICATION_PART_ROOT)
+ {
+ List *all_parts = find_all_inheritors(pubrel->prrelid, NoLock,
+ NULL);
+
+ if (pub_partopt == PUBLICATION_PART_ALL)
+ result = list_concat(result, all_parts);
+ else if (pub_partopt == PUBLICATION_PART_LEAF)
+ {
+ ListCell *lc;
+
+ foreach(lc, all_parts)
+ {
+ Oid partOid = lfirst_oid(lc);
+
+ if (get_rel_relkind(partOid) != RELKIND_PARTITIONED_TABLE)
+ result = lappend_oid(result, partOid);
+ }
+ }
+ else
+ Assert(false);
+ }
+ else
+ result = lappend_oid(result, pubrel->prrelid);
+ }
+
+ systable_endscan(scan);
+ table_close(pubrelsrel, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Gets list of publication oids for publications marked as FOR ALL TABLES.
+ */
+List *
+GetAllTablesPublications(void)
+{
+ List *result;
+ Relation rel;
+ ScanKeyData scankey;
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Find all publications that are marked as for all tables. */
+ rel = table_open(PublicationRelationId, AccessShareLock);
+
+ ScanKeyInit(&scankey,
+ Anum_pg_publication_puballtables,
+ BTEqualStrategyNumber, F_BOOLEQ,
+ BoolGetDatum(true));
+
+ scan = systable_beginscan(rel, InvalidOid, false,
+ NULL, 1, &scankey);
+
+ result = NIL;
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Oid oid = ((Form_pg_publication) GETSTRUCT(tup))->oid;
+
+ result = lappend_oid(result, oid);
+ }
+
+ systable_endscan(scan);
+ table_close(rel, AccessShareLock);
+
+ return result;
+}
+
+/*
+ * Gets list of all relation published by FOR ALL TABLES publication(s).
+ *
+ * If the publication publishes partition changes via their respective root
+ * partitioned tables, we must exclude partitions in favor of including the
+ * root partitioned tables.
+ */
+List *
+GetAllTablesPublicationRelations(bool pubviaroot)
+{
+ Relation classRel;
+ ScanKeyData key[1];
+ TableScanDesc scan;
+ HeapTuple tuple;
+ List *result = NIL;
+
+ classRel = table_open(RelationRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ CharGetDatum(RELKIND_RELATION));
+
+ scan = table_beginscan_catalog(classRel, 1, key);
+
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple);
+ Oid relid = relForm->oid;
+
+ if (is_publishable_class(relid, relForm) &&
+ !(relForm->relispartition && pubviaroot))
+ result = lappend_oid(result, relid);
+ }
+
+ table_endscan(scan);
+
+ if (pubviaroot)
+ {
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ CharGetDatum(RELKIND_PARTITIONED_TABLE));
+
+ scan = table_beginscan_catalog(classRel, 1, key);
+
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple);
+ Oid relid = relForm->oid;
+
+ if (is_publishable_class(relid, relForm) &&
+ !relForm->relispartition)
+ result = lappend_oid(result, relid);
+ }
+
+ table_endscan(scan);
+ }
+
+ table_close(classRel, AccessShareLock);
+ return result;
+}
+
+/*
+ * Get publication using oid
+ *
+ * The Publication struct and its data are palloc'ed here.
+ */
+Publication *
+GetPublication(Oid pubid)
+{
+ HeapTuple tup;
+ Publication *pub;
+ Form_pg_publication pubform;
+
+ tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for publication %u", pubid);
+
+ pubform = (Form_pg_publication) GETSTRUCT(tup);
+
+ pub = (Publication *) palloc(sizeof(Publication));
+ pub->oid = pubid;
+ pub->name = pstrdup(NameStr(pubform->pubname));
+ pub->alltables = pubform->puballtables;
+ pub->pubactions.pubinsert = pubform->pubinsert;
+ pub->pubactions.pubupdate = pubform->pubupdate;
+ pub->pubactions.pubdelete = pubform->pubdelete;
+ pub->pubactions.pubtruncate = pubform->pubtruncate;
+ pub->pubviaroot = pubform->pubviaroot;
+
+ ReleaseSysCache(tup);
+
+ return pub;
+}
+
+
+/*
+ * Get Publication using name.
+ */
+Publication *
+GetPublicationByName(const char *pubname, bool missing_ok)
+{
+ Oid oid;
+
+ oid = get_publication_oid(pubname, missing_ok);
+
+ return OidIsValid(oid) ? GetPublication(oid) : NULL;
+}
+
+/*
+ * get_publication_oid - given a publication name, look up the OID
+ *
+ * If missing_ok is false, throw an error if name not found. If true, just
+ * return InvalidOid.
+ */
+Oid
+get_publication_oid(const char *pubname, bool missing_ok)
+{
+ Oid oid;
+
+ oid = GetSysCacheOid1(PUBLICATIONNAME, Anum_pg_publication_oid,
+ CStringGetDatum(pubname));
+ if (!OidIsValid(oid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("publication \"%s\" does not exist", pubname)));
+ return oid;
+}
+
+/*
+ * get_publication_name - given a publication Oid, look up the name
+ *
+ * If missing_ok is false, throw an error if name not found. If true, just
+ * return NULL.
+ */
+char *
+get_publication_name(Oid pubid, bool missing_ok)
+{
+ HeapTuple tup;
+ char *pubname;
+ Form_pg_publication pubform;
+
+ tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
+
+ if (!HeapTupleIsValid(tup))
+ {
+ if (!missing_ok)
+ elog(ERROR, "cache lookup failed for publication %u", pubid);
+ return NULL;
+ }
+
+ pubform = (Form_pg_publication) GETSTRUCT(tup);
+ pubname = pstrdup(NameStr(pubform->pubname));
+
+ ReleaseSysCache(tup);
+
+ return pubname;
+}
+
+/*
+ * Returns Oids of tables in a publication.
+ */
+Datum
+pg_get_publication_tables(PG_FUNCTION_ARGS)
+{
+ FuncCallContext *funcctx;
+ char *pubname = text_to_cstring(PG_GETARG_TEXT_PP(0));
+ Publication *publication;
+ List *tables;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL())
+ {
+ MemoryContext oldcontext;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* switch to memory context appropriate for multiple function calls */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ publication = GetPublicationByName(pubname, false);
+
+ /*
+ * Publications support partitioned tables, although all changes are
+ * replicated using leaf partition identity and schema, so we only
+ * need those.
+ */
+ if (publication->alltables)
+ tables = GetAllTablesPublicationRelations(publication->pubviaroot);
+ else
+ tables = GetPublicationRelations(publication->oid,
+ publication->pubviaroot ?
+ PUBLICATION_PART_ROOT :
+ PUBLICATION_PART_LEAF);
+ funcctx->user_fctx = (void *) tables;
+
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+ tables = (List *) funcctx->user_fctx;
+
+ if (funcctx->call_cntr < list_length(tables))
+ {
+ Oid relid = list_nth_oid(tables, funcctx->call_cntr);
+
+ SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(relid));
+ }
+
+ SRF_RETURN_DONE(funcctx);
+}
diff --git a/src/backend/catalog/pg_publication_d.h b/src/backend/catalog/pg_publication_d.h
new file mode 100644
index 0000000..ac09853
--- /dev/null
+++ b/src/backend/catalog/pg_publication_d.h
@@ -0,0 +1,36 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_publication_d.h
+ * Macro definitions for pg_publication
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PUBLICATION_D_H
+#define PG_PUBLICATION_D_H
+
+#define PublicationRelationId 6104
+
+#define Anum_pg_publication_oid 1
+#define Anum_pg_publication_pubname 2
+#define Anum_pg_publication_pubowner 3
+#define Anum_pg_publication_puballtables 4
+#define Anum_pg_publication_pubinsert 5
+#define Anum_pg_publication_pubupdate 6
+#define Anum_pg_publication_pubdelete 7
+#define Anum_pg_publication_pubtruncate 8
+#define Anum_pg_publication_pubviaroot 9
+
+#define Natts_pg_publication 9
+
+
+#endif /* PG_PUBLICATION_D_H */
diff --git a/src/backend/catalog/pg_publication_rel_d.h b/src/backend/catalog/pg_publication_rel_d.h
new file mode 100644
index 0000000..ed1b500
--- /dev/null
+++ b/src/backend/catalog/pg_publication_rel_d.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_publication_rel_d.h
+ * Macro definitions for pg_publication_rel
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_PUBLICATION_REL_D_H
+#define PG_PUBLICATION_REL_D_H
+
+#define PublicationRelRelationId 6106
+
+#define Anum_pg_publication_rel_oid 1
+#define Anum_pg_publication_rel_prpubid 2
+#define Anum_pg_publication_rel_prrelid 3
+
+#define Natts_pg_publication_rel 3
+
+
+#endif /* PG_PUBLICATION_REL_D_H */
diff --git a/src/backend/catalog/pg_range.c b/src/backend/catalog/pg_range.c
new file mode 100644
index 0000000..b5bc36c
--- /dev/null
+++ b/src/backend/catalog/pg_range.c
@@ -0,0 +1,137 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_range.c
+ * routines to support manipulation of the pg_range relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_range.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_range.h"
+#include "catalog/pg_type.h"
+#include "utils/fmgroids.h"
+#include "utils/rel.h"
+
+
+/*
+ * RangeCreate
+ * Create an entry in pg_range.
+ */
+void
+RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
+ Oid rangeSubOpclass, RegProcedure rangeCanonical,
+ RegProcedure rangeSubDiff)
+{
+ Relation pg_range;
+ Datum values[Natts_pg_range];
+ bool nulls[Natts_pg_range];
+ HeapTuple tup;
+ ObjectAddress myself;
+ ObjectAddress referenced;
+
+ pg_range = table_open(RangeRelationId, RowExclusiveLock);
+
+ memset(nulls, 0, sizeof(nulls));
+
+ values[Anum_pg_range_rngtypid - 1] = ObjectIdGetDatum(rangeTypeOid);
+ values[Anum_pg_range_rngsubtype - 1] = ObjectIdGetDatum(rangeSubType);
+ values[Anum_pg_range_rngcollation - 1] = ObjectIdGetDatum(rangeCollation);
+ values[Anum_pg_range_rngsubopc - 1] = ObjectIdGetDatum(rangeSubOpclass);
+ values[Anum_pg_range_rngcanonical - 1] = ObjectIdGetDatum(rangeCanonical);
+ values[Anum_pg_range_rngsubdiff - 1] = ObjectIdGetDatum(rangeSubDiff);
+
+ tup = heap_form_tuple(RelationGetDescr(pg_range), values, nulls);
+
+ CatalogTupleInsert(pg_range, tup);
+ heap_freetuple(tup);
+
+ /* record type's dependencies on range-related items */
+
+ myself.classId = TypeRelationId;
+ myself.objectId = rangeTypeOid;
+ myself.objectSubId = 0;
+
+ referenced.classId = TypeRelationId;
+ referenced.objectId = rangeSubType;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ referenced.classId = OperatorClassRelationId;
+ referenced.objectId = rangeSubOpclass;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ if (OidIsValid(rangeCollation))
+ {
+ referenced.classId = CollationRelationId;
+ referenced.objectId = rangeCollation;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(rangeCanonical))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = rangeCanonical;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(rangeSubDiff))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = rangeSubDiff;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ table_close(pg_range, RowExclusiveLock);
+}
+
+
+/*
+ * RangeDelete
+ * Remove the pg_range entry for the specified type.
+ */
+void
+RangeDelete(Oid rangeTypeOid)
+{
+ Relation pg_range;
+ ScanKeyData key[1];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ pg_range = table_open(RangeRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_range_rngtypid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(rangeTypeOid));
+
+ scan = systable_beginscan(pg_range, RangeTypidIndexId, true,
+ NULL, 1, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ CatalogTupleDelete(pg_range, &tup->t_self);
+ }
+
+ systable_endscan(scan);
+
+ table_close(pg_range, RowExclusiveLock);
+}
diff --git a/src/backend/catalog/pg_range_d.h b/src/backend/catalog/pg_range_d.h
new file mode 100644
index 0000000..332a506
--- /dev/null
+++ b/src/backend/catalog/pg_range_d.h
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_range_d.h
+ * Macro definitions for pg_range
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_RANGE_D_H
+#define PG_RANGE_D_H
+
+#define RangeRelationId 3541
+
+#define Anum_pg_range_rngtypid 1
+#define Anum_pg_range_rngsubtype 2
+#define Anum_pg_range_rngcollation 3
+#define Anum_pg_range_rngsubopc 4
+#define Anum_pg_range_rngcanonical 5
+#define Anum_pg_range_rngsubdiff 6
+
+#define Natts_pg_range 6
+
+
+#endif /* PG_RANGE_D_H */
diff --git a/src/backend/catalog/pg_replication_origin_d.h b/src/backend/catalog/pg_replication_origin_d.h
new file mode 100644
index 0000000..2fcdd7c
--- /dev/null
+++ b/src/backend/catalog/pg_replication_origin_d.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_replication_origin_d.h
+ * Macro definitions for pg_replication_origin
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_REPLICATION_ORIGIN_D_H
+#define PG_REPLICATION_ORIGIN_D_H
+
+#define ReplicationOriginRelationId 6000
+
+#define Anum_pg_replication_origin_roident 1
+#define Anum_pg_replication_origin_roname 2
+
+#define Natts_pg_replication_origin 2
+
+
+#endif /* PG_REPLICATION_ORIGIN_D_H */
diff --git a/src/backend/catalog/pg_rewrite_d.h b/src/backend/catalog/pg_rewrite_d.h
new file mode 100644
index 0000000..9825de8
--- /dev/null
+++ b/src/backend/catalog/pg_rewrite_d.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_rewrite_d.h
+ * Macro definitions for pg_rewrite
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_REWRITE_D_H
+#define PG_REWRITE_D_H
+
+#define RewriteRelationId 2618
+
+#define Anum_pg_rewrite_oid 1
+#define Anum_pg_rewrite_rulename 2
+#define Anum_pg_rewrite_ev_class 3
+#define Anum_pg_rewrite_ev_type 4
+#define Anum_pg_rewrite_ev_enabled 5
+#define Anum_pg_rewrite_is_instead 6
+#define Anum_pg_rewrite_ev_qual 7
+#define Anum_pg_rewrite_ev_action 8
+
+#define Natts_pg_rewrite 8
+
+
+#endif /* PG_REWRITE_D_H */
diff --git a/src/backend/catalog/pg_seclabel_d.h b/src/backend/catalog/pg_seclabel_d.h
new file mode 100644
index 0000000..3b34c5c
--- /dev/null
+++ b/src/backend/catalog/pg_seclabel_d.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_seclabel_d.h
+ * Macro definitions for pg_seclabel
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SECLABEL_D_H
+#define PG_SECLABEL_D_H
+
+#define SecLabelRelationId 3596
+
+#define Anum_pg_seclabel_objoid 1
+#define Anum_pg_seclabel_classoid 2
+#define Anum_pg_seclabel_objsubid 3
+#define Anum_pg_seclabel_provider 4
+#define Anum_pg_seclabel_label 5
+
+#define Natts_pg_seclabel 5
+
+
+#endif /* PG_SECLABEL_D_H */
diff --git a/src/backend/catalog/pg_sequence_d.h b/src/backend/catalog/pg_sequence_d.h
new file mode 100644
index 0000000..d46c817
--- /dev/null
+++ b/src/backend/catalog/pg_sequence_d.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_sequence_d.h
+ * Macro definitions for pg_sequence
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SEQUENCE_D_H
+#define PG_SEQUENCE_D_H
+
+#define SequenceRelationId 2224
+
+#define Anum_pg_sequence_seqrelid 1
+#define Anum_pg_sequence_seqtypid 2
+#define Anum_pg_sequence_seqstart 3
+#define Anum_pg_sequence_seqincrement 4
+#define Anum_pg_sequence_seqmax 5
+#define Anum_pg_sequence_seqmin 6
+#define Anum_pg_sequence_seqcache 7
+#define Anum_pg_sequence_seqcycle 8
+
+#define Natts_pg_sequence 8
+
+
+#endif /* PG_SEQUENCE_D_H */
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
new file mode 100644
index 0000000..cac89e0
--- /dev/null
+++ b/src/backend/catalog/pg_shdepend.c
@@ -0,0 +1,1618 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_shdepend.c
+ * routines to support manipulation of the pg_shdepend relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_shdepend.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "access/xact.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_conversion.h"
+#include "catalog/pg_database.h"
+#include "catalog/pg_default_acl.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_proc.h"
+#include "catalog/pg_shdepend.h"
+#include "catalog/pg_statistic_ext.h"
+#include "catalog/pg_subscription.h"
+#include "catalog/pg_tablespace.h"
+#include "catalog/pg_ts_config.h"
+#include "catalog/pg_ts_dict.h"
+#include "catalog/pg_type.h"
+#include "catalog/pg_user_mapping.h"
+#include "commands/alter.h"
+#include "commands/collationcmds.h"
+#include "commands/conversioncmds.h"
+#include "commands/dbcommands.h"
+#include "commands/defrem.h"
+#include "commands/event_trigger.h"
+#include "commands/extension.h"
+#include "commands/policy.h"
+#include "commands/proclang.h"
+#include "commands/publicationcmds.h"
+#include "commands/schemacmds.h"
+#include "commands/subscriptioncmds.h"
+#include "commands/tablecmds.h"
+#include "commands/tablespace.h"
+#include "commands/typecmds.h"
+#include "miscadmin.h"
+#include "storage/lmgr.h"
+#include "utils/acl.h"
+#include "utils/fmgroids.h"
+#include "utils/syscache.h"
+
+typedef enum
+{
+ LOCAL_OBJECT,
+ SHARED_OBJECT,
+ REMOTE_OBJECT
+} SharedDependencyObjectType;
+
+typedef struct
+{
+ ObjectAddress object;
+ char deptype;
+ SharedDependencyObjectType objtype;
+} ShDependObjectInfo;
+
+static void getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2);
+static Oid classIdGetDbId(Oid classId);
+static void shdepChangeDep(Relation sdepRel,
+ Oid classid, Oid objid, int32 objsubid,
+ Oid refclassid, Oid refobjid,
+ SharedDependencyType deptype);
+static void shdepAddDependency(Relation sdepRel,
+ Oid classId, Oid objectId, int32 objsubId,
+ Oid refclassId, Oid refobjId,
+ SharedDependencyType deptype);
+static void shdepDropDependency(Relation sdepRel,
+ Oid classId, Oid objectId, int32 objsubId,
+ bool drop_subobjects,
+ Oid refclassId, Oid refobjId,
+ SharedDependencyType deptype);
+static void storeObjectDescription(StringInfo descs,
+ SharedDependencyObjectType type,
+ ObjectAddress *object,
+ SharedDependencyType deptype,
+ int count);
+static bool isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel);
+
+
+/*
+ * recordSharedDependencyOn
+ *
+ * Record a dependency between 2 objects via their respective ObjectAddresses.
+ * The first argument is the dependent object, the second the one it
+ * references (which must be a shared object).
+ *
+ * This locks the referenced object and makes sure it still exists.
+ * Then it creates an entry in pg_shdepend. The lock is kept until
+ * the end of the transaction.
+ *
+ * Dependencies on pinned objects are not recorded.
+ */
+void
+recordSharedDependencyOn(ObjectAddress *depender,
+ ObjectAddress *referenced,
+ SharedDependencyType deptype)
+{
+ Relation sdepRel;
+
+ /*
+ * Objects in pg_shdepend can't have SubIds.
+ */
+ Assert(depender->objectSubId == 0);
+ Assert(referenced->objectSubId == 0);
+
+ /*
+ * During bootstrap, do nothing since pg_shdepend may not exist yet.
+ * initdb will fill in appropriate pg_shdepend entries after bootstrap.
+ */
+ if (IsBootstrapProcessingMode())
+ return;
+
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+
+ /* If the referenced object is pinned, do nothing. */
+ if (!isSharedObjectPinned(referenced->classId, referenced->objectId,
+ sdepRel))
+ {
+ shdepAddDependency(sdepRel, depender->classId, depender->objectId,
+ depender->objectSubId,
+ referenced->classId, referenced->objectId,
+ deptype);
+ }
+
+ table_close(sdepRel, RowExclusiveLock);
+}
+
+/*
+ * recordDependencyOnOwner
+ *
+ * A convenient wrapper of recordSharedDependencyOn -- register the specified
+ * user as owner of the given object.
+ *
+ * Note: it's the caller's responsibility to ensure that there isn't an owner
+ * entry for the object already.
+ */
+void
+recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
+{
+ ObjectAddress myself,
+ referenced;
+
+ myself.classId = classId;
+ myself.objectId = objectId;
+ myself.objectSubId = 0;
+
+ referenced.classId = AuthIdRelationId;
+ referenced.objectId = owner;
+ referenced.objectSubId = 0;
+
+ recordSharedDependencyOn(&myself, &referenced, SHARED_DEPENDENCY_OWNER);
+}
+
+/*
+ * shdepChangeDep
+ *
+ * Update shared dependency records to account for an updated referenced
+ * object. This is an internal workhorse for operations such as changing
+ * an object's owner.
+ *
+ * There must be no more than one existing entry for the given dependent
+ * object and dependency type! So in practice this can only be used for
+ * updating SHARED_DEPENDENCY_OWNER and SHARED_DEPENDENCY_TABLESPACE
+ * entries, which should have that property.
+ *
+ * If there is no previous entry, we assume it was referencing a PINned
+ * object, so we create a new entry. If the new referenced object is
+ * PINned, we don't create an entry (and drop the old one, if any).
+ * (For tablespaces, we don't record dependencies in certain cases, so
+ * there are other possible reasons for entries to be missing.)
+ *
+ * sdepRel must be the pg_shdepend relation, already opened and suitably
+ * locked.
+ */
+static void
+shdepChangeDep(Relation sdepRel,
+ Oid classid, Oid objid, int32 objsubid,
+ Oid refclassid, Oid refobjid,
+ SharedDependencyType deptype)
+{
+ Oid dbid = classIdGetDbId(classid);
+ HeapTuple oldtup = NULL;
+ HeapTuple scantup;
+ ScanKeyData key[4];
+ SysScanDesc scan;
+
+ /*
+ * Make sure the new referenced object doesn't go away while we record the
+ * dependency.
+ */
+ shdepLockAndCheckObject(refclassid, refobjid);
+
+ /*
+ * Look for a previous entry
+ */
+ ScanKeyInit(&key[0],
+ Anum_pg_shdepend_dbid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(dbid));
+ ScanKeyInit(&key[1],
+ Anum_pg_shdepend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classid));
+ ScanKeyInit(&key[2],
+ Anum_pg_shdepend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objid));
+ ScanKeyInit(&key[3],
+ Anum_pg_shdepend_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(objsubid));
+
+ scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
+ NULL, 4, key);
+
+ while ((scantup = systable_getnext(scan)) != NULL)
+ {
+ /* Ignore if not of the target dependency type */
+ if (((Form_pg_shdepend) GETSTRUCT(scantup))->deptype != deptype)
+ continue;
+ /* Caller screwed up if multiple matches */
+ if (oldtup)
+ elog(ERROR,
+ "multiple pg_shdepend entries for object %u/%u/%d deptype %c",
+ classid, objid, objsubid, deptype);
+ oldtup = heap_copytuple(scantup);
+ }
+
+ systable_endscan(scan);
+
+ if (isSharedObjectPinned(refclassid, refobjid, sdepRel))
+ {
+ /* No new entry needed, so just delete existing entry if any */
+ if (oldtup)
+ CatalogTupleDelete(sdepRel, &oldtup->t_self);
+ }
+ else if (oldtup)
+ {
+ /* Need to update existing entry */
+ Form_pg_shdepend shForm = (Form_pg_shdepend) GETSTRUCT(oldtup);
+
+ /* Since oldtup is a copy, we can just modify it in-memory */
+ shForm->refclassid = refclassid;
+ shForm->refobjid = refobjid;
+
+ CatalogTupleUpdate(sdepRel, &oldtup->t_self, oldtup);
+ }
+ else
+ {
+ /* Need to insert new entry */
+ Datum values[Natts_pg_shdepend];
+ bool nulls[Natts_pg_shdepend];
+
+ memset(nulls, false, sizeof(nulls));
+
+ values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(dbid);
+ values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classid);
+ values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objid);
+ values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubid);
+
+ values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassid);
+ values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjid);
+ values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
+
+ /*
+ * we are reusing oldtup just to avoid declaring a new variable, but
+ * it's certainly a new tuple
+ */
+ oldtup = heap_form_tuple(RelationGetDescr(sdepRel), values, nulls);
+ CatalogTupleInsert(sdepRel, oldtup);
+ }
+
+ if (oldtup)
+ heap_freetuple(oldtup);
+}
+
+/*
+ * changeDependencyOnOwner
+ *
+ * Update the shared dependencies to account for the new owner.
+ *
+ * Note: we don't need an objsubid argument because only whole objects
+ * have owners.
+ */
+void
+changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
+{
+ Relation sdepRel;
+
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+
+ /* Adjust the SHARED_DEPENDENCY_OWNER entry */
+ shdepChangeDep(sdepRel,
+ classId, objectId, 0,
+ AuthIdRelationId, newOwnerId,
+ SHARED_DEPENDENCY_OWNER);
+
+ /*----------
+ * There should never be a SHARED_DEPENDENCY_ACL entry for the owner,
+ * so get rid of it if there is one. This can happen if the new owner
+ * was previously granted some rights to the object.
+ *
+ * This step is analogous to aclnewowner's removal of duplicate entries
+ * in the ACL. We have to do it to handle this scenario:
+ * A grants some rights on an object to B
+ * ALTER OWNER changes the object's owner to B
+ * ALTER OWNER changes the object's owner to C
+ * The third step would remove all mention of B from the object's ACL,
+ * but we'd still have a SHARED_DEPENDENCY_ACL for B if we did not do
+ * things this way.
+ *
+ * The rule against having a SHARED_DEPENDENCY_ACL entry for the owner
+ * allows us to fix things up in just this one place, without having
+ * to make the various ALTER OWNER routines each know about it.
+ *----------
+ */
+ shdepDropDependency(sdepRel, classId, objectId, 0, true,
+ AuthIdRelationId, newOwnerId,
+ SHARED_DEPENDENCY_ACL);
+
+ table_close(sdepRel, RowExclusiveLock);
+}
+
+/*
+ * recordDependencyOnTablespace
+ *
+ * A convenient wrapper of recordSharedDependencyOn -- register the specified
+ * tablespace as default for the given object.
+ *
+ * Note: it's the caller's responsibility to ensure that there isn't a
+ * tablespace entry for the object already.
+ */
+void
+recordDependencyOnTablespace(Oid classId, Oid objectId, Oid tablespace)
+{
+ ObjectAddress myself,
+ referenced;
+
+ ObjectAddressSet(myself, classId, objectId);
+ ObjectAddressSet(referenced, TableSpaceRelationId, tablespace);
+
+ recordSharedDependencyOn(&myself, &referenced,
+ SHARED_DEPENDENCY_TABLESPACE);
+}
+
+/*
+ * changeDependencyOnTablespace
+ *
+ * Update the shared dependencies to account for the new tablespace.
+ *
+ * Note: we don't need an objsubid argument because only whole objects
+ * have tablespaces.
+ */
+void
+changeDependencyOnTablespace(Oid classId, Oid objectId, Oid newTablespaceId)
+{
+ Relation sdepRel;
+
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+
+ if (newTablespaceId != DEFAULTTABLESPACE_OID &&
+ newTablespaceId != InvalidOid)
+ shdepChangeDep(sdepRel,
+ classId, objectId, 0,
+ TableSpaceRelationId, newTablespaceId,
+ SHARED_DEPENDENCY_TABLESPACE);
+ else
+ shdepDropDependency(sdepRel,
+ classId, objectId, 0, true,
+ InvalidOid, InvalidOid,
+ SHARED_DEPENDENCY_INVALID);
+
+ table_close(sdepRel, RowExclusiveLock);
+}
+
+/*
+ * getOidListDiff
+ * Helper for updateAclDependencies.
+ *
+ * Takes two Oid arrays and removes elements that are common to both arrays,
+ * leaving just those that are in one input but not the other.
+ * We assume both arrays have been sorted and de-duped.
+ */
+static void
+getOidListDiff(Oid *list1, int *nlist1, Oid *list2, int *nlist2)
+{
+ int in1,
+ in2,
+ out1,
+ out2;
+
+ in1 = in2 = out1 = out2 = 0;
+ while (in1 < *nlist1 && in2 < *nlist2)
+ {
+ if (list1[in1] == list2[in2])
+ {
+ /* skip over duplicates */
+ in1++;
+ in2++;
+ }
+ else if (list1[in1] < list2[in2])
+ {
+ /* list1[in1] is not in list2 */
+ list1[out1++] = list1[in1++];
+ }
+ else
+ {
+ /* list2[in2] is not in list1 */
+ list2[out2++] = list2[in2++];
+ }
+ }
+
+ /* any remaining list1 entries are not in list2 */
+ while (in1 < *nlist1)
+ {
+ list1[out1++] = list1[in1++];
+ }
+
+ /* any remaining list2 entries are not in list1 */
+ while (in2 < *nlist2)
+ {
+ list2[out2++] = list2[in2++];
+ }
+
+ *nlist1 = out1;
+ *nlist2 = out2;
+}
+
+/*
+ * updateAclDependencies
+ * Update the pg_shdepend info for an object's ACL during GRANT/REVOKE.
+ *
+ * classId, objectId, objsubId: identify the object whose ACL this is
+ * ownerId: role owning the object
+ * noldmembers, oldmembers: array of roleids appearing in old ACL
+ * nnewmembers, newmembers: array of roleids appearing in new ACL
+ *
+ * We calculate the differences between the new and old lists of roles,
+ * and then insert or delete from pg_shdepend as appropriate.
+ *
+ * Note that we can't just insert all referenced roles blindly during GRANT,
+ * because we would end up with duplicate registered dependencies. We could
+ * check for existence of the tuples before inserting, but that seems to be
+ * more expensive than what we are doing here. Likewise we can't just delete
+ * blindly during REVOKE, because the user may still have other privileges.
+ * It is also possible that REVOKE actually adds dependencies, due to
+ * instantiation of a formerly implicit default ACL (although at present,
+ * all such dependencies should be for the owning role, which we ignore here).
+ *
+ * NOTE: Both input arrays must be sorted and de-duped. (Typically they
+ * are extracted from an ACL array by aclmembers(), which takes care of
+ * both requirements.) The arrays are pfreed before return.
+ */
+void
+updateAclDependencies(Oid classId, Oid objectId, int32 objsubId,
+ Oid ownerId,
+ int noldmembers, Oid *oldmembers,
+ int nnewmembers, Oid *newmembers)
+{
+ Relation sdepRel;
+ int i;
+
+ /*
+ * Remove entries that are common to both lists; those represent existing
+ * dependencies we don't need to change.
+ *
+ * OK to overwrite the inputs since we'll pfree them anyway.
+ */
+ getOidListDiff(oldmembers, &noldmembers, newmembers, &nnewmembers);
+
+ if (noldmembers > 0 || nnewmembers > 0)
+ {
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+
+ /* Add new dependencies that weren't already present */
+ for (i = 0; i < nnewmembers; i++)
+ {
+ Oid roleid = newmembers[i];
+
+ /*
+ * Skip the owner: he has an OWNER shdep entry instead. (This is
+ * not just a space optimization; it makes ALTER OWNER easier. See
+ * notes in changeDependencyOnOwner.)
+ */
+ if (roleid == ownerId)
+ continue;
+
+ /* Skip pinned roles; they don't need dependency entries */
+ if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
+ continue;
+
+ shdepAddDependency(sdepRel, classId, objectId, objsubId,
+ AuthIdRelationId, roleid,
+ SHARED_DEPENDENCY_ACL);
+ }
+
+ /* Drop no-longer-used old dependencies */
+ for (i = 0; i < noldmembers; i++)
+ {
+ Oid roleid = oldmembers[i];
+
+ /* Skip the owner, same as above */
+ if (roleid == ownerId)
+ continue;
+
+ /* Skip pinned roles */
+ if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
+ continue;
+
+ shdepDropDependency(sdepRel, classId, objectId, objsubId,
+ false, /* exact match on objsubId */
+ AuthIdRelationId, roleid,
+ SHARED_DEPENDENCY_ACL);
+ }
+
+ table_close(sdepRel, RowExclusiveLock);
+ }
+
+ if (oldmembers)
+ pfree(oldmembers);
+ if (newmembers)
+ pfree(newmembers);
+}
+
+/*
+ * A struct to keep track of dependencies found in other databases.
+ */
+typedef struct
+{
+ Oid dbOid;
+ int count;
+} remoteDep;
+
+/*
+ * qsort comparator for ShDependObjectInfo items
+ */
+static int
+shared_dependency_comparator(const void *a, const void *b)
+{
+ const ShDependObjectInfo *obja = (const ShDependObjectInfo *) a;
+ const ShDependObjectInfo *objb = (const ShDependObjectInfo *) b;
+
+ /*
+ * Primary sort key is OID ascending.
+ */
+ if (obja->object.objectId < objb->object.objectId)
+ return -1;
+ if (obja->object.objectId > objb->object.objectId)
+ return 1;
+
+ /*
+ * Next sort on catalog ID, in case identical OIDs appear in different
+ * catalogs. Sort direction is pretty arbitrary here.
+ */
+ if (obja->object.classId < objb->object.classId)
+ return -1;
+ if (obja->object.classId > objb->object.classId)
+ return 1;
+
+ /*
+ * Sort on object subId.
+ *
+ * We sort the subId as an unsigned int so that 0 (the whole object) will
+ * come first.
+ */
+ if ((unsigned int) obja->object.objectSubId < (unsigned int) objb->object.objectSubId)
+ return -1;
+ if ((unsigned int) obja->object.objectSubId > (unsigned int) objb->object.objectSubId)
+ return 1;
+
+ /*
+ * Last, sort on deptype, in case the same object has multiple dependency
+ * types. (Note that there's no need to consider objtype, as that's
+ * determined by the catalog OID.)
+ */
+ if (obja->deptype < objb->deptype)
+ return -1;
+ if (obja->deptype > objb->deptype)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * checkSharedDependencies
+ *
+ * Check whether there are shared dependency entries for a given shared
+ * object; return true if so.
+ *
+ * In addition, return a string containing a newline-separated list of object
+ * descriptions that depend on the shared object, or NULL if none is found.
+ * We actually return two such strings; the "detail" result is suitable for
+ * returning to the client as an errdetail() string, and is limited in size.
+ * The "detail_log" string is potentially much longer, and should be emitted
+ * to the server log only.
+ *
+ * We can find three different kinds of dependencies: dependencies on objects
+ * of the current database; dependencies on shared objects; and dependencies
+ * on objects local to other databases. We can (and do) provide descriptions
+ * of the two former kinds of objects, but we can't do that for "remote"
+ * objects, so we just provide a count of them.
+ *
+ * If we find a SHARED_DEPENDENCY_PIN entry, we can error out early.
+ */
+bool
+checkSharedDependencies(Oid classId, Oid objectId,
+ char **detail_msg, char **detail_log_msg)
+{
+ Relation sdepRel;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+ int numReportedDeps = 0;
+ int numNotReportedDeps = 0;
+ int numNotReportedDbs = 0;
+ List *remDeps = NIL;
+ ListCell *cell;
+ ObjectAddress object;
+ ShDependObjectInfo *objects;
+ int numobjects;
+ int allocedobjects;
+ StringInfoData descs;
+ StringInfoData alldescs;
+
+ /*
+ * We limit the number of dependencies reported to the client to
+ * MAX_REPORTED_DEPS, since client software may not deal well with
+ * enormous error strings. The server log always gets a full report.
+ *
+ * For stability of regression test results, we sort local and shared
+ * objects by OID before reporting them. We don't worry about the order
+ * in which other databases are reported, though.
+ */
+#define MAX_REPORTED_DEPS 100
+
+ allocedobjects = 128; /* arbitrary initial array size */
+ objects = (ShDependObjectInfo *)
+ palloc(allocedobjects * sizeof(ShDependObjectInfo));
+ numobjects = 0;
+ initStringInfo(&descs);
+ initStringInfo(&alldescs);
+
+ sdepRel = table_open(SharedDependRelationId, AccessShareLock);
+
+ ScanKeyInit(&key[0],
+ Anum_pg_shdepend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_shdepend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
+ NULL, 2, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
+
+ /* This case can be dispatched quickly */
+ if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
+ {
+ object.classId = classId;
+ object.objectId = objectId;
+ object.objectSubId = 0;
+ ereport(ERROR,
+ (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+ errmsg("cannot drop %s because it is required by the database system",
+ getObjectDescription(&object))));
+ }
+
+ object.classId = sdepForm->classid;
+ object.objectId = sdepForm->objid;
+ object.objectSubId = sdepForm->objsubid;
+
+ /*
+ * If it's a dependency local to this database or it's a shared
+ * object, add it to the objects array.
+ *
+ * If it's a remote dependency, keep track of it so we can report the
+ * number of them later.
+ */
+ if (sdepForm->dbid == MyDatabaseId ||
+ sdepForm->dbid == InvalidOid)
+ {
+ if (numobjects >= allocedobjects)
+ {
+ allocedobjects *= 2;
+ objects = (ShDependObjectInfo *)
+ repalloc(objects,
+ allocedobjects * sizeof(ShDependObjectInfo));
+ }
+ objects[numobjects].object = object;
+ objects[numobjects].deptype = sdepForm->deptype;
+ objects[numobjects].objtype = (sdepForm->dbid == MyDatabaseId) ?
+ LOCAL_OBJECT : SHARED_OBJECT;
+ numobjects++;
+ }
+ else
+ {
+ /* It's not local nor shared, so it must be remote. */
+ remoteDep *dep;
+ bool stored = false;
+
+ /*
+ * XXX this info is kept on a simple List. Maybe it's not good
+ * for performance, but using a hash table seems needlessly
+ * complex. The expected number of databases is not high anyway,
+ * I suppose.
+ */
+ foreach(cell, remDeps)
+ {
+ dep = lfirst(cell);
+ if (dep->dbOid == sdepForm->dbid)
+ {
+ dep->count++;
+ stored = true;
+ break;
+ }
+ }
+ if (!stored)
+ {
+ dep = (remoteDep *) palloc(sizeof(remoteDep));
+ dep->dbOid = sdepForm->dbid;
+ dep->count = 1;
+ remDeps = lappend(remDeps, dep);
+ }
+ }
+ }
+
+ systable_endscan(scan);
+
+ table_close(sdepRel, AccessShareLock);
+
+ /*
+ * Sort and report local and shared objects.
+ */
+ if (numobjects > 1)
+ qsort((void *) objects, numobjects,
+ sizeof(ShDependObjectInfo), shared_dependency_comparator);
+
+ for (int i = 0; i < numobjects; i++)
+ {
+ if (numReportedDeps < MAX_REPORTED_DEPS)
+ {
+ numReportedDeps++;
+ storeObjectDescription(&descs,
+ objects[i].objtype,
+ &objects[i].object,
+ objects[i].deptype,
+ 0);
+ }
+ else
+ numNotReportedDeps++;
+ storeObjectDescription(&alldescs,
+ objects[i].objtype,
+ &objects[i].object,
+ objects[i].deptype,
+ 0);
+ }
+
+ /*
+ * Summarize dependencies in remote databases.
+ */
+ foreach(cell, remDeps)
+ {
+ remoteDep *dep = lfirst(cell);
+
+ object.classId = DatabaseRelationId;
+ object.objectId = dep->dbOid;
+ object.objectSubId = 0;
+
+ if (numReportedDeps < MAX_REPORTED_DEPS)
+ {
+ numReportedDeps++;
+ storeObjectDescription(&descs, REMOTE_OBJECT, &object,
+ SHARED_DEPENDENCY_INVALID, dep->count);
+ }
+ else
+ numNotReportedDbs++;
+ storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
+ SHARED_DEPENDENCY_INVALID, dep->count);
+ }
+
+ pfree(objects);
+ list_free_deep(remDeps);
+
+ if (descs.len == 0)
+ {
+ pfree(descs.data);
+ pfree(alldescs.data);
+ *detail_msg = *detail_log_msg = NULL;
+ return false;
+ }
+
+ if (numNotReportedDeps > 0)
+ appendStringInfo(&descs, ngettext("\nand %d other object "
+ "(see server log for list)",
+ "\nand %d other objects "
+ "(see server log for list)",
+ numNotReportedDeps),
+ numNotReportedDeps);
+ if (numNotReportedDbs > 0)
+ appendStringInfo(&descs, ngettext("\nand objects in %d other database "
+ "(see server log for list)",
+ "\nand objects in %d other databases "
+ "(see server log for list)",
+ numNotReportedDbs),
+ numNotReportedDbs);
+
+ *detail_msg = descs.data;
+ *detail_log_msg = alldescs.data;
+ return true;
+}
+
+/*
+ * copyTemplateDependencies
+ *
+ * Routine to create the initial shared dependencies of a new database.
+ * We simply copy the dependencies from the template database.
+ */
+void
+copyTemplateDependencies(Oid templateDbId, Oid newDbId)
+{
+ Relation sdepRel;
+ TupleDesc sdepDesc;
+ ScanKeyData key[1];
+ SysScanDesc scan;
+ HeapTuple tup;
+ CatalogIndexState indstate;
+ Datum values[Natts_pg_shdepend];
+ bool nulls[Natts_pg_shdepend];
+ bool replace[Natts_pg_shdepend];
+
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+ sdepDesc = RelationGetDescr(sdepRel);
+
+ indstate = CatalogOpenIndexes(sdepRel);
+
+ /* Scan all entries with dbid = templateDbId */
+ ScanKeyInit(&key[0],
+ Anum_pg_shdepend_dbid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(templateDbId));
+
+ scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
+ NULL, 1, key);
+
+ /* Set up to copy the tuples except for inserting newDbId */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replace, false, sizeof(replace));
+
+ replace[Anum_pg_shdepend_dbid - 1] = true;
+ values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(newDbId);
+
+ /*
+ * Copy the entries of the original database, changing the database Id to
+ * that of the new database. Note that because we are not copying rows
+ * with dbId == 0 (ie, rows describing dependent shared objects) we won't
+ * copy the ownership dependency of the template database itself; this is
+ * what we want.
+ */
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ HeapTuple newtup;
+
+ newtup = heap_modify_tuple(tup, sdepDesc, values, nulls, replace);
+ CatalogTupleInsertWithInfo(sdepRel, newtup, indstate);
+
+ heap_freetuple(newtup);
+ }
+
+ systable_endscan(scan);
+
+ CatalogCloseIndexes(indstate);
+ table_close(sdepRel, RowExclusiveLock);
+}
+
+/*
+ * dropDatabaseDependencies
+ *
+ * Delete pg_shdepend entries corresponding to a database that's being
+ * dropped.
+ */
+void
+dropDatabaseDependencies(Oid databaseId)
+{
+ Relation sdepRel;
+ ScanKeyData key[1];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+
+ /*
+ * First, delete all the entries that have the database Oid in the dbid
+ * field.
+ */
+ ScanKeyInit(&key[0],
+ Anum_pg_shdepend_dbid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(databaseId));
+ /* We leave the other index fields unspecified */
+
+ scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
+ NULL, 1, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ CatalogTupleDelete(sdepRel, &tup->t_self);
+ }
+
+ systable_endscan(scan);
+
+ /* Now delete all entries corresponding to the database itself */
+ shdepDropDependency(sdepRel, DatabaseRelationId, databaseId, 0, true,
+ InvalidOid, InvalidOid,
+ SHARED_DEPENDENCY_INVALID);
+
+ table_close(sdepRel, RowExclusiveLock);
+}
+
+/*
+ * deleteSharedDependencyRecordsFor
+ *
+ * Delete all pg_shdepend entries corresponding to an object that's being
+ * dropped or modified. The object is assumed to be either a shared object
+ * or local to the current database (the classId tells us which).
+ *
+ * If objectSubId is zero, we are deleting a whole object, so get rid of
+ * pg_shdepend entries for subobjects as well.
+ */
+void
+deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
+{
+ Relation sdepRel;
+
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+
+ shdepDropDependency(sdepRel, classId, objectId, objectSubId,
+ (objectSubId == 0),
+ InvalidOid, InvalidOid,
+ SHARED_DEPENDENCY_INVALID);
+
+ table_close(sdepRel, RowExclusiveLock);
+}
+
+/*
+ * shdepAddDependency
+ * Internal workhorse for inserting into pg_shdepend
+ *
+ * sdepRel must be the pg_shdepend relation, already opened and suitably
+ * locked.
+ */
+static void
+shdepAddDependency(Relation sdepRel,
+ Oid classId, Oid objectId, int32 objsubId,
+ Oid refclassId, Oid refobjId,
+ SharedDependencyType deptype)
+{
+ HeapTuple tup;
+ Datum values[Natts_pg_shdepend];
+ bool nulls[Natts_pg_shdepend];
+
+ /*
+ * Make sure the object doesn't go away while we record the dependency on
+ * it. DROP routines should lock the object exclusively before they check
+ * shared dependencies.
+ */
+ shdepLockAndCheckObject(refclassId, refobjId);
+
+ memset(nulls, false, sizeof(nulls));
+
+ /*
+ * Form the new tuple and record the dependency.
+ */
+ values[Anum_pg_shdepend_dbid - 1] = ObjectIdGetDatum(classIdGetDbId(classId));
+ values[Anum_pg_shdepend_classid - 1] = ObjectIdGetDatum(classId);
+ values[Anum_pg_shdepend_objid - 1] = ObjectIdGetDatum(objectId);
+ values[Anum_pg_shdepend_objsubid - 1] = Int32GetDatum(objsubId);
+
+ values[Anum_pg_shdepend_refclassid - 1] = ObjectIdGetDatum(refclassId);
+ values[Anum_pg_shdepend_refobjid - 1] = ObjectIdGetDatum(refobjId);
+ values[Anum_pg_shdepend_deptype - 1] = CharGetDatum(deptype);
+
+ tup = heap_form_tuple(sdepRel->rd_att, values, nulls);
+
+ CatalogTupleInsert(sdepRel, tup);
+
+ /* clean up */
+ heap_freetuple(tup);
+}
+
+/*
+ * shdepDropDependency
+ * Internal workhorse for deleting entries from pg_shdepend.
+ *
+ * We drop entries having the following properties:
+ * dependent object is the one identified by classId/objectId/objsubId
+ * if refclassId isn't InvalidOid, it must match the entry's refclassid
+ * if refobjId isn't InvalidOid, it must match the entry's refobjid
+ * if deptype isn't SHARED_DEPENDENCY_INVALID, it must match entry's deptype
+ *
+ * If drop_subobjects is true, we ignore objsubId and consider all entries
+ * matching classId/objectId.
+ *
+ * sdepRel must be the pg_shdepend relation, already opened and suitably
+ * locked.
+ */
+static void
+shdepDropDependency(Relation sdepRel,
+ Oid classId, Oid objectId, int32 objsubId,
+ bool drop_subobjects,
+ Oid refclassId, Oid refobjId,
+ SharedDependencyType deptype)
+{
+ ScanKeyData key[4];
+ int nkeys;
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ /* Scan for entries matching the dependent object */
+ ScanKeyInit(&key[0],
+ Anum_pg_shdepend_dbid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classIdGetDbId(classId)));
+ ScanKeyInit(&key[1],
+ Anum_pg_shdepend_classid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[2],
+ Anum_pg_shdepend_objid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+ if (drop_subobjects)
+ nkeys = 3;
+ else
+ {
+ ScanKeyInit(&key[3],
+ Anum_pg_shdepend_objsubid,
+ BTEqualStrategyNumber, F_INT4EQ,
+ Int32GetDatum(objsubId));
+ nkeys = 4;
+ }
+
+ scan = systable_beginscan(sdepRel, SharedDependDependerIndexId, true,
+ NULL, nkeys, key);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
+
+ /* Filter entries according to additional parameters */
+ if (OidIsValid(refclassId) && shdepForm->refclassid != refclassId)
+ continue;
+ if (OidIsValid(refobjId) && shdepForm->refobjid != refobjId)
+ continue;
+ if (deptype != SHARED_DEPENDENCY_INVALID &&
+ shdepForm->deptype != deptype)
+ continue;
+
+ /* OK, delete it */
+ CatalogTupleDelete(sdepRel, &tup->t_self);
+ }
+
+ systable_endscan(scan);
+}
+
+/*
+ * classIdGetDbId
+ *
+ * Get the database Id that should be used in pg_shdepend, given the OID
+ * of the catalog containing the object. For shared objects, it's 0
+ * (InvalidOid); for all other objects, it's the current database Id.
+ */
+static Oid
+classIdGetDbId(Oid classId)
+{
+ Oid dbId;
+
+ if (IsSharedRelation(classId))
+ dbId = InvalidOid;
+ else
+ dbId = MyDatabaseId;
+
+ return dbId;
+}
+
+/*
+ * shdepLockAndCheckObject
+ *
+ * Lock the object that we are about to record a dependency on.
+ * After it's locked, verify that it hasn't been dropped while we
+ * weren't looking. If the object has been dropped, this function
+ * does not return!
+ */
+void
+shdepLockAndCheckObject(Oid classId, Oid objectId)
+{
+ /* AccessShareLock should be OK, since we are not modifying the object */
+ LockSharedObject(classId, objectId, 0, AccessShareLock);
+
+ switch (classId)
+ {
+ case AuthIdRelationId:
+ if (!SearchSysCacheExists1(AUTHOID, ObjectIdGetDatum(objectId)))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("role %u was concurrently dropped",
+ objectId)));
+ break;
+
+ case TableSpaceRelationId:
+ {
+ /* For lack of a syscache on pg_tablespace, do this: */
+ char *tablespace = get_tablespace_name(objectId);
+
+ if (tablespace == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("tablespace %u was concurrently dropped",
+ objectId)));
+ pfree(tablespace);
+ break;
+ }
+
+ case DatabaseRelationId:
+ {
+ /* For lack of a syscache on pg_database, do this: */
+ char *database = get_database_name(objectId);
+
+ if (database == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("database %u was concurrently dropped",
+ objectId)));
+ pfree(database);
+ break;
+ }
+
+
+ default:
+ elog(ERROR, "unrecognized shared classId: %u", classId);
+ }
+}
+
+
+/*
+ * storeObjectDescription
+ * Append the description of a dependent object to "descs"
+ *
+ * While searching for dependencies of a shared object, we stash the
+ * descriptions of dependent objects we find in a single string, which we
+ * later pass to ereport() in the DETAIL field when somebody attempts to
+ * drop a referenced shared object.
+ *
+ * When type is LOCAL_OBJECT or SHARED_OBJECT, we expect object to be the
+ * dependent object, deptype is the dependency type, and count is not used.
+ * When type is REMOTE_OBJECT, we expect object to be the database object,
+ * and count to be nonzero; deptype is not used in this case.
+ */
+static void
+storeObjectDescription(StringInfo descs,
+ SharedDependencyObjectType type,
+ ObjectAddress *object,
+ SharedDependencyType deptype,
+ int count)
+{
+ char *objdesc = getObjectDescription(object);
+
+ /* separate entries with a newline */
+ if (descs->len != 0)
+ appendStringInfoChar(descs, '\n');
+
+ switch (type)
+ {
+ case LOCAL_OBJECT:
+ case SHARED_OBJECT:
+ if (deptype == SHARED_DEPENDENCY_OWNER)
+ appendStringInfo(descs, _("owner of %s"), objdesc);
+ else if (deptype == SHARED_DEPENDENCY_ACL)
+ appendStringInfo(descs, _("privileges for %s"), objdesc);
+ else if (deptype == SHARED_DEPENDENCY_POLICY)
+ appendStringInfo(descs, _("target of %s"), objdesc);
+ else if (deptype == SHARED_DEPENDENCY_TABLESPACE)
+ appendStringInfo(descs, _("tablespace for %s"), objdesc);
+ else
+ elog(ERROR, "unrecognized dependency type: %d",
+ (int) deptype);
+ break;
+
+ case REMOTE_OBJECT:
+ /* translator: %s will always be "database %s" */
+ appendStringInfo(descs, ngettext("%d object in %s",
+ "%d objects in %s",
+ count),
+ count, objdesc);
+ break;
+
+ default:
+ elog(ERROR, "unrecognized object type: %d", type);
+ }
+
+ pfree(objdesc);
+}
+
+
+/*
+ * isSharedObjectPinned
+ * Return whether a given shared object has a SHARED_DEPENDENCY_PIN entry.
+ *
+ * sdepRel must be the pg_shdepend relation, already opened and suitably
+ * locked.
+ */
+static bool
+isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
+{
+ bool result = false;
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ ScanKeyInit(&key[0],
+ Anum_pg_shdepend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(classId));
+ ScanKeyInit(&key[1],
+ Anum_pg_shdepend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(objectId));
+
+ scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
+ NULL, 2, key);
+
+ /*
+ * Since we won't generate additional pg_shdepend entries for pinned
+ * objects, there can be at most one entry referencing a pinned object.
+ * Hence, it's sufficient to look at the first returned tuple; we don't
+ * need to loop.
+ */
+ tup = systable_getnext(scan);
+ if (HeapTupleIsValid(tup))
+ {
+ Form_pg_shdepend shdepForm = (Form_pg_shdepend) GETSTRUCT(tup);
+
+ if (shdepForm->deptype == SHARED_DEPENDENCY_PIN)
+ result = true;
+ }
+
+ systable_endscan(scan);
+
+ return result;
+}
+
+/*
+ * shdepDropOwned
+ *
+ * Drop the objects owned by any one of the given RoleIds. If a role has
+ * access to an object, the grant will be removed as well (but the object
+ * will not, of course).
+ *
+ * We can revoke grants immediately while doing the scan, but drops are
+ * saved up and done all at once with performMultipleDeletions. This
+ * is necessary so that we don't get failures from trying to delete
+ * interdependent objects in the wrong order.
+ */
+void
+shdepDropOwned(List *roleids, DropBehavior behavior)
+{
+ Relation sdepRel;
+ ListCell *cell;
+ ObjectAddresses *deleteobjs;
+
+ deleteobjs = new_object_addresses();
+
+ /*
+ * We don't need this strong a lock here, but we'll call routines that
+ * acquire RowExclusiveLock. Better get that right now to avoid potential
+ * deadlock failures.
+ */
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+
+ /*
+ * For each role, find the dependent objects and drop them using the
+ * regular (non-shared) dependency management.
+ */
+ foreach(cell, roleids)
+ {
+ Oid roleid = lfirst_oid(cell);
+ ScanKeyData key[2];
+ SysScanDesc scan;
+ HeapTuple tuple;
+
+ /* Doesn't work for pinned objects */
+ if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
+ {
+ ObjectAddress obj;
+
+ obj.classId = AuthIdRelationId;
+ obj.objectId = roleid;
+ obj.objectSubId = 0;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+ errmsg("cannot drop objects owned by %s because they are "
+ "required by the database system",
+ getObjectDescription(&obj))));
+ }
+
+ ScanKeyInit(&key[0],
+ Anum_pg_shdepend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(AuthIdRelationId));
+ ScanKeyInit(&key[1],
+ Anum_pg_shdepend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(roleid));
+
+ scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
+ NULL, 2, key);
+
+ while ((tuple = systable_getnext(scan)) != NULL)
+ {
+ Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
+ ObjectAddress obj;
+
+ /*
+ * We only operate on shared objects and objects in the current
+ * database
+ */
+ if (sdepForm->dbid != MyDatabaseId &&
+ sdepForm->dbid != InvalidOid)
+ continue;
+
+ switch (sdepForm->deptype)
+ {
+ /* Shouldn't happen */
+ case SHARED_DEPENDENCY_PIN:
+ case SHARED_DEPENDENCY_INVALID:
+ elog(ERROR, "unexpected dependency type");
+ break;
+ case SHARED_DEPENDENCY_ACL:
+ RemoveRoleFromObjectACL(roleid,
+ sdepForm->classid,
+ sdepForm->objid);
+ break;
+ case SHARED_DEPENDENCY_POLICY:
+
+ /*
+ * Try to remove role from policy; if unable to, remove
+ * policy.
+ */
+ if (!RemoveRoleFromObjectPolicy(roleid,
+ sdepForm->classid,
+ sdepForm->objid))
+ {
+ obj.classId = sdepForm->classid;
+ obj.objectId = sdepForm->objid;
+ obj.objectSubId = sdepForm->objsubid;
+
+ /*
+ * Acquire lock on object, then verify this dependency
+ * is still relevant. If not, the object might have
+ * been dropped or the policy modified. Ignore the
+ * object in that case.
+ */
+ AcquireDeletionLock(&obj, 0);
+ if (!systable_recheck_tuple(scan, tuple))
+ {
+ ReleaseDeletionLock(&obj);
+ break;
+ }
+ add_exact_object_address(&obj, deleteobjs);
+ }
+ break;
+ case SHARED_DEPENDENCY_OWNER:
+ /* If a local object, save it for deletion below */
+ if (sdepForm->dbid == MyDatabaseId)
+ {
+ obj.classId = sdepForm->classid;
+ obj.objectId = sdepForm->objid;
+ obj.objectSubId = sdepForm->objsubid;
+ /* as above */
+ AcquireDeletionLock(&obj, 0);
+ if (!systable_recheck_tuple(scan, tuple))
+ {
+ ReleaseDeletionLock(&obj);
+ break;
+ }
+ add_exact_object_address(&obj, deleteobjs);
+ }
+ break;
+ }
+ }
+
+ systable_endscan(scan);
+ }
+
+ /*
+ * For stability of deletion-report ordering, sort the objects into
+ * approximate reverse creation order before deletion. (This might also
+ * make the deletion go a bit faster, since there's less chance of having
+ * to rearrange the objects due to dependencies.)
+ */
+ sort_object_addresses(deleteobjs);
+
+ /* the dependency mechanism does the actual work */
+ performMultipleDeletions(deleteobjs, behavior, 0);
+
+ table_close(sdepRel, RowExclusiveLock);
+
+ free_object_addresses(deleteobjs);
+}
+
+/*
+ * shdepReassignOwned
+ *
+ * Change the owner of objects owned by any of the roles in roleids to
+ * newrole. Grants are not touched.
+ */
+void
+shdepReassignOwned(List *roleids, Oid newrole)
+{
+ Relation sdepRel;
+ ListCell *cell;
+
+ /*
+ * We don't need this strong a lock here, but we'll call routines that
+ * acquire RowExclusiveLock. Better get that right now to avoid potential
+ * deadlock problems.
+ */
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+
+ foreach(cell, roleids)
+ {
+ SysScanDesc scan;
+ ScanKeyData key[2];
+ HeapTuple tuple;
+ Oid roleid = lfirst_oid(cell);
+
+ /* Refuse to work on pinned roles */
+ if (isSharedObjectPinned(AuthIdRelationId, roleid, sdepRel))
+ {
+ ObjectAddress obj;
+
+ obj.classId = AuthIdRelationId;
+ obj.objectId = roleid;
+ obj.objectSubId = 0;
+
+ ereport(ERROR,
+ (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+ errmsg("cannot reassign ownership of objects owned by %s because they are required by the database system",
+ getObjectDescription(&obj))));
+
+ /*
+ * There's no need to tell the whole truth, which is that we
+ * didn't track these dependencies at all ...
+ */
+ }
+
+ ScanKeyInit(&key[0],
+ Anum_pg_shdepend_refclassid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(AuthIdRelationId));
+ ScanKeyInit(&key[1],
+ Anum_pg_shdepend_refobjid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(roleid));
+
+ scan = systable_beginscan(sdepRel, SharedDependReferenceIndexId, true,
+ NULL, 2, key);
+
+ while ((tuple = systable_getnext(scan)) != NULL)
+ {
+ Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
+
+ /*
+ * We only operate on shared objects and objects in the current
+ * database
+ */
+ if (sdepForm->dbid != MyDatabaseId &&
+ sdepForm->dbid != InvalidOid)
+ continue;
+
+ /* Unexpected because we checked for pins above */
+ if (sdepForm->deptype == SHARED_DEPENDENCY_PIN)
+ elog(ERROR, "unexpected shared pin");
+
+ /* We leave non-owner dependencies alone */
+ if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
+ continue;
+
+ /* Issue the appropriate ALTER OWNER call */
+ switch (sdepForm->classid)
+ {
+ case TypeRelationId:
+ AlterTypeOwner_oid(sdepForm->objid, newrole, true);
+ break;
+
+ case NamespaceRelationId:
+ AlterSchemaOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case RelationRelationId:
+
+ /*
+ * Pass recursing = true so that we don't fail on indexes,
+ * owned sequences, etc when we happen to visit them
+ * before their parent table.
+ */
+ ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
+ break;
+
+ case DefaultAclRelationId:
+
+ /*
+ * Ignore default ACLs; they should be handled by DROP
+ * OWNED, not REASSIGN OWNED.
+ */
+ break;
+
+ case UserMappingRelationId:
+ /* ditto */
+ break;
+
+ case ForeignServerRelationId:
+ AlterForeignServerOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case ForeignDataWrapperRelationId:
+ AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case EventTriggerRelationId:
+ AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case PublicationRelationId:
+ AlterPublicationOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ case SubscriptionRelationId:
+ AlterSubscriptionOwner_oid(sdepForm->objid, newrole);
+ break;
+
+ /* Generic alter owner cases */
+ case CollationRelationId:
+ case ConversionRelationId:
+ case OperatorRelationId:
+ case ProcedureRelationId:
+ case LanguageRelationId:
+ case LargeObjectRelationId:
+ case OperatorFamilyRelationId:
+ case OperatorClassRelationId:
+ case ExtensionRelationId:
+ case StatisticExtRelationId:
+ case TableSpaceRelationId:
+ case DatabaseRelationId:
+ case TSConfigRelationId:
+ case TSDictionaryRelationId:
+ {
+ Oid classId = sdepForm->classid;
+ Relation catalog;
+
+ if (classId == LargeObjectRelationId)
+ classId = LargeObjectMetadataRelationId;
+
+ catalog = table_open(classId, RowExclusiveLock);
+
+ AlterObjectOwner_internal(catalog, sdepForm->objid,
+ newrole);
+
+ table_close(catalog, NoLock);
+ }
+ break;
+
+ default:
+ elog(ERROR, "unexpected classid %u", sdepForm->classid);
+ break;
+ }
+ /* Make sure the next iteration will see my changes */
+ CommandCounterIncrement();
+ }
+
+ systable_endscan(scan);
+ }
+
+ table_close(sdepRel, RowExclusiveLock);
+}
diff --git a/src/backend/catalog/pg_shdepend_d.h b/src/backend/catalog/pg_shdepend_d.h
new file mode 100644
index 0000000..b62d5c9
--- /dev/null
+++ b/src/backend/catalog/pg_shdepend_d.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_shdepend_d.h
+ * Macro definitions for pg_shdepend
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SHDEPEND_D_H
+#define PG_SHDEPEND_D_H
+
+#define SharedDependRelationId 1214
+
+#define Anum_pg_shdepend_dbid 1
+#define Anum_pg_shdepend_classid 2
+#define Anum_pg_shdepend_objid 3
+#define Anum_pg_shdepend_objsubid 4
+#define Anum_pg_shdepend_refclassid 5
+#define Anum_pg_shdepend_refobjid 6
+#define Anum_pg_shdepend_deptype 7
+
+#define Natts_pg_shdepend 7
+
+
+#endif /* PG_SHDEPEND_D_H */
diff --git a/src/backend/catalog/pg_shdescription_d.h b/src/backend/catalog/pg_shdescription_d.h
new file mode 100644
index 0000000..238da96
--- /dev/null
+++ b/src/backend/catalog/pg_shdescription_d.h
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_shdescription_d.h
+ * Macro definitions for pg_shdescription
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SHDESCRIPTION_D_H
+#define PG_SHDESCRIPTION_D_H
+
+#define SharedDescriptionRelationId 2396
+
+#define Anum_pg_shdescription_objoid 1
+#define Anum_pg_shdescription_classoid 2
+#define Anum_pg_shdescription_description 3
+
+#define Natts_pg_shdescription 3
+
+
+#endif /* PG_SHDESCRIPTION_D_H */
diff --git a/src/backend/catalog/pg_shseclabel_d.h b/src/backend/catalog/pg_shseclabel_d.h
new file mode 100644
index 0000000..f6058f3
--- /dev/null
+++ b/src/backend/catalog/pg_shseclabel_d.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_shseclabel_d.h
+ * Macro definitions for pg_shseclabel
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SHSECLABEL_D_H
+#define PG_SHSECLABEL_D_H
+
+#define SharedSecLabelRelationId 3592
+#define SharedSecLabelRelation_Rowtype_Id 4066
+
+#define Anum_pg_shseclabel_objoid 1
+#define Anum_pg_shseclabel_classoid 2
+#define Anum_pg_shseclabel_provider 3
+#define Anum_pg_shseclabel_label 4
+
+#define Natts_pg_shseclabel 4
+
+
+#endif /* PG_SHSECLABEL_D_H */
diff --git a/src/backend/catalog/pg_statistic_d.h b/src/backend/catalog/pg_statistic_d.h
new file mode 100644
index 0000000..1174daa
--- /dev/null
+++ b/src/backend/catalog/pg_statistic_d.h
@@ -0,0 +1,194 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_statistic_d.h
+ * Macro definitions for pg_statistic
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_STATISTIC_D_H
+#define PG_STATISTIC_D_H
+
+#define StatisticRelationId 2619
+
+#define Anum_pg_statistic_starelid 1
+#define Anum_pg_statistic_staattnum 2
+#define Anum_pg_statistic_stainherit 3
+#define Anum_pg_statistic_stanullfrac 4
+#define Anum_pg_statistic_stawidth 5
+#define Anum_pg_statistic_stadistinct 6
+#define Anum_pg_statistic_stakind1 7
+#define Anum_pg_statistic_stakind2 8
+#define Anum_pg_statistic_stakind3 9
+#define Anum_pg_statistic_stakind4 10
+#define Anum_pg_statistic_stakind5 11
+#define Anum_pg_statistic_staop1 12
+#define Anum_pg_statistic_staop2 13
+#define Anum_pg_statistic_staop3 14
+#define Anum_pg_statistic_staop4 15
+#define Anum_pg_statistic_staop5 16
+#define Anum_pg_statistic_stacoll1 17
+#define Anum_pg_statistic_stacoll2 18
+#define Anum_pg_statistic_stacoll3 19
+#define Anum_pg_statistic_stacoll4 20
+#define Anum_pg_statistic_stacoll5 21
+#define Anum_pg_statistic_stanumbers1 22
+#define Anum_pg_statistic_stanumbers2 23
+#define Anum_pg_statistic_stanumbers3 24
+#define Anum_pg_statistic_stanumbers4 25
+#define Anum_pg_statistic_stanumbers5 26
+#define Anum_pg_statistic_stavalues1 27
+#define Anum_pg_statistic_stavalues2 28
+#define Anum_pg_statistic_stavalues3 29
+#define Anum_pg_statistic_stavalues4 30
+#define Anum_pg_statistic_stavalues5 31
+
+#define Natts_pg_statistic 31
+
+
+/*
+ * Several statistical slot "kinds" are defined by core PostgreSQL, as
+ * documented below. Also, custom data types can define their own "kind"
+ * codes by mutual agreement between a custom typanalyze routine and the
+ * selectivity estimation functions of the type's operators.
+ *
+ * Code reading the pg_statistic relation should not assume that a particular
+ * data "kind" will appear in any particular slot. Instead, search the
+ * stakind fields to see if the desired data is available. (The standard
+ * function get_attstatsslot() may be used for this.)
+ */
+
+/*
+ * The present allocation of "kind" codes is:
+ *
+ * 1-99: reserved for assignment by the core PostgreSQL project
+ * (values in this range will be documented in this file)
+ * 100-199: reserved for assignment by the PostGIS project
+ * (values to be documented in PostGIS documentation)
+ * 200-299: reserved for assignment by the ESRI ST_Geometry project
+ * (values to be documented in ESRI ST_Geometry documentation)
+ * 300-9999: reserved for future public assignments
+ *
+ * For private use you may choose a "kind" code at random in the range
+ * 10000-30000. However, for code that is to be widely disseminated it is
+ * better to obtain a publicly defined "kind" code by request from the
+ * PostgreSQL Global Development Group.
+ */
+
+/*
+ * In a "most common values" slot, staop is the OID of the "=" operator
+ * used to decide whether values are the same or not, and stacoll is the
+ * collation used (same as column's collation). stavalues contains
+ * the K most common non-null values appearing in the column, and stanumbers
+ * contains their frequencies (fractions of total row count). The values
+ * shall be ordered in decreasing frequency. Note that since the arrays are
+ * variable-size, K may be chosen by the statistics collector. Values should
+ * not appear in MCV unless they have been observed to occur more than once;
+ * a unique column will have no MCV slot.
+ */
+#define STATISTIC_KIND_MCV 1
+
+/*
+ * A "histogram" slot describes the distribution of scalar data. staop is
+ * the OID of the "<" operator that describes the sort ordering, and stacoll
+ * is the relevant collation. (In theory more than one histogram could appear,
+ * if a datatype has more than one useful sort operator or we care about more
+ * than one collation. Currently the collation will always be that of the
+ * underlying column.) stavalues contains M (>=2) non-null values that
+ * divide the non-null column data values into M-1 bins of approximately equal
+ * population. The first stavalues item is the MIN and the last is the MAX.
+ * stanumbers is not used and should be NULL. IMPORTANT POINT: if an MCV
+ * slot is also provided, then the histogram describes the data distribution
+ * *after removing the values listed in MCV* (thus, it's a "compressed
+ * histogram" in the technical parlance). This allows a more accurate
+ * representation of the distribution of a column with some very-common
+ * values. In a column with only a few distinct values, it's possible that
+ * the MCV list describes the entire data population; in this case the
+ * histogram reduces to empty and should be omitted.
+ */
+#define STATISTIC_KIND_HISTOGRAM 2
+
+/*
+ * A "correlation" slot describes the correlation between the physical order
+ * of table tuples and the ordering of data values of this column, as seen
+ * by the "<" operator identified by staop with the collation identified by
+ * stacoll. (As with the histogram, more than one entry could theoretically
+ * appear.) stavalues is not used and should be NULL. stanumbers contains
+ * a single entry, the correlation coefficient between the sequence of data
+ * values and the sequence of their actual tuple positions. The coefficient
+ * ranges from +1 to -1.
+ */
+#define STATISTIC_KIND_CORRELATION 3
+
+/*
+ * A "most common elements" slot is similar to a "most common values" slot,
+ * except that it stores the most common non-null *elements* of the column
+ * values. This is useful when the column datatype is an array or some other
+ * type with identifiable elements (for instance, tsvector). staop contains
+ * the equality operator appropriate to the element type, and stacoll
+ * contains the collation to use with it. stavalues contains
+ * the most common element values, and stanumbers their frequencies. Unlike
+ * MCV slots, frequencies are measured as the fraction of non-null rows the
+ * element value appears in, not the frequency of all rows. Also unlike
+ * MCV slots, the values are sorted into the element type's default order
+ * (to support binary search for a particular value). Since this puts the
+ * minimum and maximum frequencies at unpredictable spots in stanumbers,
+ * there are two extra members of stanumbers, holding copies of the minimum
+ * and maximum frequencies. Optionally, there can be a third extra member,
+ * which holds the frequency of null elements (expressed in the same terms:
+ * the fraction of non-null rows that contain at least one null element). If
+ * this member is omitted, the column is presumed to contain no null elements.
+ *
+ * Note: in current usage for tsvector columns, the stavalues elements are of
+ * type text, even though their representation within tsvector is not
+ * exactly text.
+ */
+#define STATISTIC_KIND_MCELEM 4
+
+/*
+ * A "distinct elements count histogram" slot describes the distribution of
+ * the number of distinct element values present in each row of an array-type
+ * column. Only non-null rows are considered, and only non-null elements.
+ * staop contains the equality operator appropriate to the element type,
+ * and stacoll contains the collation to use with it.
+ * stavalues is not used and should be NULL. The last member of stanumbers is
+ * the average count of distinct element values over all non-null rows. The
+ * preceding M (>=2) members form a histogram that divides the population of
+ * distinct-elements counts into M-1 bins of approximately equal population.
+ * The first of these is the minimum observed count, and the last the maximum.
+ */
+#define STATISTIC_KIND_DECHIST 5
+
+/*
+ * A "length histogram" slot describes the distribution of range lengths in
+ * rows of a range-type column. stanumbers contains a single entry, the
+ * fraction of empty ranges. stavalues is a histogram of non-empty lengths, in
+ * a format similar to STATISTIC_KIND_HISTOGRAM: it contains M (>=2) range
+ * values that divide the column data values into M-1 bins of approximately
+ * equal population. The lengths are stored as float8s, as measured by the
+ * range type's subdiff function. Only non-null rows are considered.
+ */
+#define STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM 6
+
+/*
+ * A "bounds histogram" slot is similar to STATISTIC_KIND_HISTOGRAM, but for
+ * a range-type column. stavalues contains M (>=2) range values that divide
+ * the column data values into M-1 bins of approximately equal population.
+ * Unlike a regular scalar histogram, this is actually two histograms combined
+ * into a single array, with the lower bounds of each value forming a
+ * histogram of lower bounds, and the upper bounds a histogram of upper
+ * bounds. Only non-NULL, non-empty ranges are included.
+ */
+#define STATISTIC_KIND_BOUNDS_HISTOGRAM 7
+
+
+#endif /* PG_STATISTIC_D_H */
diff --git a/src/backend/catalog/pg_statistic_ext_d.h b/src/backend/catalog/pg_statistic_ext_d.h
new file mode 100644
index 0000000..809e97e
--- /dev/null
+++ b/src/backend/catalog/pg_statistic_ext_d.h
@@ -0,0 +1,40 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_statistic_ext_d.h
+ * Macro definitions for pg_statistic_ext
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_STATISTIC_EXT_D_H
+#define PG_STATISTIC_EXT_D_H
+
+#define StatisticExtRelationId 3381
+
+#define Anum_pg_statistic_ext_oid 1
+#define Anum_pg_statistic_ext_stxrelid 2
+#define Anum_pg_statistic_ext_stxname 3
+#define Anum_pg_statistic_ext_stxnamespace 4
+#define Anum_pg_statistic_ext_stxowner 5
+#define Anum_pg_statistic_ext_stxstattarget 6
+#define Anum_pg_statistic_ext_stxkeys 7
+#define Anum_pg_statistic_ext_stxkind 8
+
+#define Natts_pg_statistic_ext 8
+
+
+#define STATS_EXT_NDISTINCT 'd'
+#define STATS_EXT_DEPENDENCIES 'f'
+#define STATS_EXT_MCV 'm'
+
+
+#endif /* PG_STATISTIC_EXT_D_H */
diff --git a/src/backend/catalog/pg_statistic_ext_data_d.h b/src/backend/catalog/pg_statistic_ext_data_d.h
new file mode 100644
index 0000000..79df16d
--- /dev/null
+++ b/src/backend/catalog/pg_statistic_ext_data_d.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_statistic_ext_data_d.h
+ * Macro definitions for pg_statistic_ext_data
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_STATISTIC_EXT_DATA_D_H
+#define PG_STATISTIC_EXT_DATA_D_H
+
+#define StatisticExtDataRelationId 3429
+
+#define Anum_pg_statistic_ext_data_stxoid 1
+#define Anum_pg_statistic_ext_data_stxdndistinct 2
+#define Anum_pg_statistic_ext_data_stxddependencies 3
+#define Anum_pg_statistic_ext_data_stxdmcv 4
+
+#define Natts_pg_statistic_ext_data 4
+
+
+#endif /* PG_STATISTIC_EXT_DATA_D_H */
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
new file mode 100644
index 0000000..0d23b20
--- /dev/null
+++ b/src/backend/catalog/pg_subscription.c
@@ -0,0 +1,536 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_subscription.c
+ * replication subscriptions
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_subscription.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/tableam.h"
+#include "access/xact.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_subscription.h"
+#include "catalog/pg_subscription_rel.h"
+#include "catalog/pg_type.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "storage/lmgr.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/pg_lsn.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+static List *textarray_to_stringlist(ArrayType *textarray);
+
+/*
+ * Fetch the subscription from the syscache.
+ */
+Subscription *
+GetSubscription(Oid subid, bool missing_ok)
+{
+ HeapTuple tup;
+ Subscription *sub;
+ Form_pg_subscription subform;
+ Datum datum;
+ bool isnull;
+
+ tup = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(subid));
+
+ if (!HeapTupleIsValid(tup))
+ {
+ if (missing_ok)
+ return NULL;
+
+ elog(ERROR, "cache lookup failed for subscription %u", subid);
+ }
+
+ subform = (Form_pg_subscription) GETSTRUCT(tup);
+
+ sub = (Subscription *) palloc(sizeof(Subscription));
+ sub->oid = subid;
+ sub->dbid = subform->subdbid;
+ sub->name = pstrdup(NameStr(subform->subname));
+ sub->owner = subform->subowner;
+ sub->enabled = subform->subenabled;
+
+ /* Get conninfo */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID,
+ tup,
+ Anum_pg_subscription_subconninfo,
+ &isnull);
+ Assert(!isnull);
+ sub->conninfo = TextDatumGetCString(datum);
+
+ /* Get slotname */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID,
+ tup,
+ Anum_pg_subscription_subslotname,
+ &isnull);
+ if (!isnull)
+ sub->slotname = pstrdup(NameStr(*DatumGetName(datum)));
+ else
+ sub->slotname = NULL;
+
+ /* Get synccommit */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID,
+ tup,
+ Anum_pg_subscription_subsynccommit,
+ &isnull);
+ Assert(!isnull);
+ sub->synccommit = TextDatumGetCString(datum);
+
+ /* Get publications */
+ datum = SysCacheGetAttr(SUBSCRIPTIONOID,
+ tup,
+ Anum_pg_subscription_subpublications,
+ &isnull);
+ Assert(!isnull);
+ sub->publications = textarray_to_stringlist(DatumGetArrayTypeP(datum));
+
+ ReleaseSysCache(tup);
+
+ return sub;
+}
+
+/*
+ * Return number of subscriptions defined in given database.
+ * Used by dropdb() to check if database can indeed be dropped.
+ */
+int
+CountDBSubscriptions(Oid dbid)
+{
+ int nsubs = 0;
+ Relation rel;
+ ScanKeyData scankey;
+ SysScanDesc scan;
+ HeapTuple tup;
+
+ rel = table_open(SubscriptionRelationId, RowExclusiveLock);
+
+ ScanKeyInit(&scankey,
+ Anum_pg_subscription_subdbid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(dbid));
+
+ scan = systable_beginscan(rel, InvalidOid, false,
+ NULL, 1, &scankey);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ nsubs++;
+
+ systable_endscan(scan);
+
+ table_close(rel, NoLock);
+
+ return nsubs;
+}
+
+/*
+ * Free memory allocated by subscription struct.
+ */
+void
+FreeSubscription(Subscription *sub)
+{
+ pfree(sub->name);
+ pfree(sub->conninfo);
+ if (sub->slotname)
+ pfree(sub->slotname);
+ list_free_deep(sub->publications);
+ pfree(sub);
+}
+
+/*
+ * get_subscription_oid - given a subscription name, look up the OID
+ *
+ * If missing_ok is false, throw an error if name not found. If true, just
+ * return InvalidOid.
+ */
+Oid
+get_subscription_oid(const char *subname, bool missing_ok)
+{
+ Oid oid;
+
+ oid = GetSysCacheOid2(SUBSCRIPTIONNAME, Anum_pg_subscription_oid,
+ MyDatabaseId, CStringGetDatum(subname));
+ if (!OidIsValid(oid) && !missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("subscription \"%s\" does not exist", subname)));
+ return oid;
+}
+
+/*
+ * get_subscription_name - given a subscription OID, look up the name
+ *
+ * If missing_ok is false, throw an error if name not found. If true, just
+ * return NULL.
+ */
+char *
+get_subscription_name(Oid subid, bool missing_ok)
+{
+ HeapTuple tup;
+ char *subname;
+ Form_pg_subscription subform;
+
+ tup = SearchSysCache1(SUBSCRIPTIONOID, ObjectIdGetDatum(subid));
+
+ if (!HeapTupleIsValid(tup))
+ {
+ if (!missing_ok)
+ elog(ERROR, "cache lookup failed for subscription %u", subid);
+ return NULL;
+ }
+
+ subform = (Form_pg_subscription) GETSTRUCT(tup);
+ subname = pstrdup(NameStr(subform->subname));
+
+ ReleaseSysCache(tup);
+
+ return subname;
+}
+
+/*
+ * Convert text array to list of strings.
+ *
+ * Note: the resulting list of strings is pallocated here.
+ */
+static List *
+textarray_to_stringlist(ArrayType *textarray)
+{
+ Datum *elems;
+ int nelems,
+ i;
+ List *res = NIL;
+
+ deconstruct_array(textarray,
+ TEXTOID, -1, false, TYPALIGN_INT,
+ &elems, NULL, &nelems);
+
+ if (nelems == 0)
+ return NIL;
+
+ for (i = 0; i < nelems; i++)
+ res = lappend(res, makeString(TextDatumGetCString(elems[i])));
+
+ return res;
+}
+
+/*
+ * Add new state record for a subscription table.
+ */
+void
+AddSubscriptionRelState(Oid subid, Oid relid, char state,
+ XLogRecPtr sublsn)
+{
+ Relation rel;
+ HeapTuple tup;
+ bool nulls[Natts_pg_subscription_rel];
+ Datum values[Natts_pg_subscription_rel];
+
+ LockSharedObject(SubscriptionRelationId, subid, 0, AccessShareLock);
+
+ rel = table_open(SubscriptionRelRelationId, RowExclusiveLock);
+
+ /* Try finding existing mapping. */
+ tup = SearchSysCacheCopy2(SUBSCRIPTIONRELMAP,
+ ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(subid));
+ if (HeapTupleIsValid(tup))
+ elog(ERROR, "subscription table %u in subscription %u already exists",
+ relid, subid);
+
+ /* Form the tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ values[Anum_pg_subscription_rel_srsubid - 1] = ObjectIdGetDatum(subid);
+ values[Anum_pg_subscription_rel_srrelid - 1] = ObjectIdGetDatum(relid);
+ values[Anum_pg_subscription_rel_srsubstate - 1] = CharGetDatum(state);
+ if (sublsn != InvalidXLogRecPtr)
+ values[Anum_pg_subscription_rel_srsublsn - 1] = LSNGetDatum(sublsn);
+ else
+ nulls[Anum_pg_subscription_rel_srsublsn - 1] = true;
+
+ tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+
+ /* Insert tuple into catalog. */
+ CatalogTupleInsert(rel, tup);
+
+ heap_freetuple(tup);
+
+ /* Cleanup. */
+ table_close(rel, NoLock);
+}
+
+/*
+ * Update the state of a subscription table.
+ */
+void
+UpdateSubscriptionRelState(Oid subid, Oid relid, char state,
+ XLogRecPtr sublsn)
+{
+ Relation rel;
+ HeapTuple tup;
+ bool nulls[Natts_pg_subscription_rel];
+ Datum values[Natts_pg_subscription_rel];
+ bool replaces[Natts_pg_subscription_rel];
+
+ LockSharedObject(SubscriptionRelationId, subid, 0, AccessShareLock);
+
+ rel = table_open(SubscriptionRelRelationId, RowExclusiveLock);
+
+ /* Try finding existing mapping. */
+ tup = SearchSysCacheCopy2(SUBSCRIPTIONRELMAP,
+ ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(subid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "subscription table %u in subscription %u does not exist",
+ relid, subid);
+
+ /* Update the tuple. */
+ memset(values, 0, sizeof(values));
+ memset(nulls, false, sizeof(nulls));
+ memset(replaces, false, sizeof(replaces));
+
+ replaces[Anum_pg_subscription_rel_srsubstate - 1] = true;
+ values[Anum_pg_subscription_rel_srsubstate - 1] = CharGetDatum(state);
+
+ replaces[Anum_pg_subscription_rel_srsublsn - 1] = true;
+ if (sublsn != InvalidXLogRecPtr)
+ values[Anum_pg_subscription_rel_srsublsn - 1] = LSNGetDatum(sublsn);
+ else
+ nulls[Anum_pg_subscription_rel_srsublsn - 1] = true;
+
+ tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
+ replaces);
+
+ /* Update the catalog. */
+ CatalogTupleUpdate(rel, &tup->t_self, tup);
+
+ /* Cleanup. */
+ table_close(rel, NoLock);
+}
+
+/*
+ * Get state of subscription table.
+ *
+ * Returns SUBREL_STATE_UNKNOWN when not found and missing_ok is true.
+ */
+char
+GetSubscriptionRelState(Oid subid, Oid relid, XLogRecPtr *sublsn,
+ bool missing_ok)
+{
+ Relation rel;
+ HeapTuple tup;
+ char substate;
+ bool isnull;
+ Datum d;
+
+ rel = table_open(SubscriptionRelRelationId, AccessShareLock);
+
+ /* Try finding the mapping. */
+ tup = SearchSysCache2(SUBSCRIPTIONRELMAP,
+ ObjectIdGetDatum(relid),
+ ObjectIdGetDatum(subid));
+
+ if (!HeapTupleIsValid(tup))
+ {
+ if (missing_ok)
+ {
+ table_close(rel, AccessShareLock);
+ *sublsn = InvalidXLogRecPtr;
+ return SUBREL_STATE_UNKNOWN;
+ }
+
+ elog(ERROR, "subscription table %u in subscription %u does not exist",
+ relid, subid);
+ }
+
+ /* Get the state. */
+ d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
+ Anum_pg_subscription_rel_srsubstate, &isnull);
+ Assert(!isnull);
+ substate = DatumGetChar(d);
+ d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
+ Anum_pg_subscription_rel_srsublsn, &isnull);
+ if (isnull)
+ *sublsn = InvalidXLogRecPtr;
+ else
+ *sublsn = DatumGetLSN(d);
+
+ /* Cleanup */
+ ReleaseSysCache(tup);
+ table_close(rel, AccessShareLock);
+
+ return substate;
+}
+
+/*
+ * Drop subscription relation mapping. These can be for a particular
+ * subscription, or for a particular relation, or both.
+ */
+void
+RemoveSubscriptionRel(Oid subid, Oid relid)
+{
+ Relation rel;
+ TableScanDesc scan;
+ ScanKeyData skey[2];
+ HeapTuple tup;
+ int nkeys = 0;
+
+ rel = table_open(SubscriptionRelRelationId, RowExclusiveLock);
+
+ if (OidIsValid(subid))
+ {
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srsubid,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(subid));
+ }
+
+ if (OidIsValid(relid))
+ {
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srrelid,
+ BTEqualStrategyNumber,
+ F_OIDEQ,
+ ObjectIdGetDatum(relid));
+ }
+
+ /* Do the search and delete what we found. */
+ scan = table_beginscan_catalog(rel, nkeys, skey);
+ while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
+ {
+ CatalogTupleDelete(rel, &tup->t_self);
+ }
+ table_endscan(scan);
+
+ table_close(rel, RowExclusiveLock);
+}
+
+
+/*
+ * Get all relations for subscription.
+ *
+ * Returned list is palloc'ed in current memory context.
+ */
+List *
+GetSubscriptionRelations(Oid subid)
+{
+ List *res = NIL;
+ Relation rel;
+ HeapTuple tup;
+ int nkeys = 0;
+ ScanKeyData skey[2];
+ SysScanDesc scan;
+
+ rel = table_open(SubscriptionRelRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srsubid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(subid));
+
+ scan = systable_beginscan(rel, InvalidOid, false,
+ NULL, nkeys, skey);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_subscription_rel subrel;
+ SubscriptionRelState *relstate;
+ Datum d;
+ bool isnull;
+
+ subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);
+
+ relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState));
+ relstate->relid = subrel->srrelid;
+ relstate->state = subrel->srsubstate;
+ d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
+ Anum_pg_subscription_rel_srsublsn, &isnull);
+ if (isnull)
+ relstate->lsn = InvalidXLogRecPtr;
+ else
+ relstate->lsn = DatumGetLSN(d);
+
+ res = lappend(res, relstate);
+ }
+
+ /* Cleanup */
+ systable_endscan(scan);
+ table_close(rel, AccessShareLock);
+
+ return res;
+}
+
+/*
+ * Get all relations for subscription that are not in a ready state.
+ *
+ * Returned list is palloc'ed in current memory context.
+ */
+List *
+GetSubscriptionNotReadyRelations(Oid subid)
+{
+ List *res = NIL;
+ Relation rel;
+ HeapTuple tup;
+ int nkeys = 0;
+ ScanKeyData skey[2];
+ SysScanDesc scan;
+
+ rel = table_open(SubscriptionRelRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srsubid,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(subid));
+
+ ScanKeyInit(&skey[nkeys++],
+ Anum_pg_subscription_rel_srsubstate,
+ BTEqualStrategyNumber, F_CHARNE,
+ CharGetDatum(SUBREL_STATE_READY));
+
+ scan = systable_beginscan(rel, InvalidOid, false,
+ NULL, nkeys, skey);
+
+ while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ {
+ Form_pg_subscription_rel subrel;
+ SubscriptionRelState *relstate;
+ Datum d;
+ bool isnull;
+
+ subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);
+
+ relstate = (SubscriptionRelState *) palloc(sizeof(SubscriptionRelState));
+ relstate->relid = subrel->srrelid;
+ relstate->state = subrel->srsubstate;
+ d = SysCacheGetAttr(SUBSCRIPTIONRELMAP, tup,
+ Anum_pg_subscription_rel_srsublsn, &isnull);
+ if (isnull)
+ relstate->lsn = InvalidXLogRecPtr;
+ else
+ relstate->lsn = DatumGetLSN(d);
+
+ res = lappend(res, relstate);
+ }
+
+ /* Cleanup */
+ systable_endscan(scan);
+ table_close(rel, AccessShareLock);
+
+ return res;
+}
diff --git a/src/backend/catalog/pg_subscription_d.h b/src/backend/catalog/pg_subscription_d.h
new file mode 100644
index 0000000..de5c027
--- /dev/null
+++ b/src/backend/catalog/pg_subscription_d.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_subscription_d.h
+ * Macro definitions for pg_subscription
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SUBSCRIPTION_D_H
+#define PG_SUBSCRIPTION_D_H
+
+#define SubscriptionRelationId 6100
+#define SubscriptionRelation_Rowtype_Id 6101
+
+#define Anum_pg_subscription_oid 1
+#define Anum_pg_subscription_subdbid 2
+#define Anum_pg_subscription_subname 3
+#define Anum_pg_subscription_subowner 4
+#define Anum_pg_subscription_subenabled 5
+#define Anum_pg_subscription_subconninfo 6
+#define Anum_pg_subscription_subslotname 7
+#define Anum_pg_subscription_subsynccommit 8
+#define Anum_pg_subscription_subpublications 9
+
+#define Natts_pg_subscription 9
+
+
+#endif /* PG_SUBSCRIPTION_D_H */
diff --git a/src/backend/catalog/pg_subscription_rel_d.h b/src/backend/catalog/pg_subscription_rel_d.h
new file mode 100644
index 0000000..71ec769
--- /dev/null
+++ b/src/backend/catalog/pg_subscription_rel_d.h
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_subscription_rel_d.h
+ * Macro definitions for pg_subscription_rel
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_SUBSCRIPTION_REL_D_H
+#define PG_SUBSCRIPTION_REL_D_H
+
+#define SubscriptionRelRelationId 6102
+
+#define Anum_pg_subscription_rel_srsubid 1
+#define Anum_pg_subscription_rel_srrelid 2
+#define Anum_pg_subscription_rel_srsubstate 3
+#define Anum_pg_subscription_rel_srsublsn 4
+
+#define Natts_pg_subscription_rel 4
+
+
+/* ----------------
+ * substate constants
+ * ----------------
+ */
+#define SUBREL_STATE_INIT 'i' /* initializing (sublsn NULL) */
+#define SUBREL_STATE_DATASYNC 'd' /* data is being synchronized (sublsn
+ * NULL) */
+#define SUBREL_STATE_SYNCDONE 's' /* synchronization finished in front of
+ * apply (sublsn set) */
+#define SUBREL_STATE_READY 'r' /* ready (sublsn set) */
+
+/* These are never stored in the catalog, we only use them for IPC. */
+#define SUBREL_STATE_UNKNOWN '\0' /* unknown state */
+#define SUBREL_STATE_SYNCWAIT 'w' /* waiting for sync */
+#define SUBREL_STATE_CATCHUP 'c' /* catching up with apply */
+
+
+#endif /* PG_SUBSCRIPTION_REL_D_H */
diff --git a/src/backend/catalog/pg_tablespace_d.h b/src/backend/catalog/pg_tablespace_d.h
new file mode 100644
index 0000000..c66ad17
--- /dev/null
+++ b/src/backend/catalog/pg_tablespace_d.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_tablespace_d.h
+ * Macro definitions for pg_tablespace
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TABLESPACE_D_H
+#define PG_TABLESPACE_D_H
+
+#define TableSpaceRelationId 1213
+
+#define Anum_pg_tablespace_oid 1
+#define Anum_pg_tablespace_spcname 2
+#define Anum_pg_tablespace_spcowner 3
+#define Anum_pg_tablespace_spcacl 4
+#define Anum_pg_tablespace_spcoptions 5
+
+#define Natts_pg_tablespace 5
+
+#define DEFAULTTABLESPACE_OID 1663
+#define GLOBALTABLESPACE_OID 1664
+
+#endif /* PG_TABLESPACE_D_H */
diff --git a/src/backend/catalog/pg_transform_d.h b/src/backend/catalog/pg_transform_d.h
new file mode 100644
index 0000000..3bc064b
--- /dev/null
+++ b/src/backend/catalog/pg_transform_d.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_transform_d.h
+ * Macro definitions for pg_transform
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TRANSFORM_D_H
+#define PG_TRANSFORM_D_H
+
+#define TransformRelationId 3576
+
+#define Anum_pg_transform_oid 1
+#define Anum_pg_transform_trftype 2
+#define Anum_pg_transform_trflang 3
+#define Anum_pg_transform_trffromsql 4
+#define Anum_pg_transform_trftosql 5
+
+#define Natts_pg_transform 5
+
+
+#endif /* PG_TRANSFORM_D_H */
diff --git a/src/backend/catalog/pg_trigger_d.h b/src/backend/catalog/pg_trigger_d.h
new file mode 100644
index 0000000..90d3058
--- /dev/null
+++ b/src/backend/catalog/pg_trigger_d.h
@@ -0,0 +1,106 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_trigger_d.h
+ * Macro definitions for pg_trigger
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TRIGGER_D_H
+#define PG_TRIGGER_D_H
+
+#define TriggerRelationId 2620
+
+#define Anum_pg_trigger_oid 1
+#define Anum_pg_trigger_tgrelid 2
+#define Anum_pg_trigger_tgparentid 3
+#define Anum_pg_trigger_tgname 4
+#define Anum_pg_trigger_tgfoid 5
+#define Anum_pg_trigger_tgtype 6
+#define Anum_pg_trigger_tgenabled 7
+#define Anum_pg_trigger_tgisinternal 8
+#define Anum_pg_trigger_tgconstrrelid 9
+#define Anum_pg_trigger_tgconstrindid 10
+#define Anum_pg_trigger_tgconstraint 11
+#define Anum_pg_trigger_tgdeferrable 12
+#define Anum_pg_trigger_tginitdeferred 13
+#define Anum_pg_trigger_tgnargs 14
+#define Anum_pg_trigger_tgattr 15
+#define Anum_pg_trigger_tgargs 16
+#define Anum_pg_trigger_tgqual 17
+#define Anum_pg_trigger_tgoldtable 18
+#define Anum_pg_trigger_tgnewtable 19
+
+#define Natts_pg_trigger 19
+
+
+/* Bits within tgtype */
+#define TRIGGER_TYPE_ROW (1 << 0)
+#define TRIGGER_TYPE_BEFORE (1 << 1)
+#define TRIGGER_TYPE_INSERT (1 << 2)
+#define TRIGGER_TYPE_DELETE (1 << 3)
+#define TRIGGER_TYPE_UPDATE (1 << 4)
+#define TRIGGER_TYPE_TRUNCATE (1 << 5)
+#define TRIGGER_TYPE_INSTEAD (1 << 6)
+
+#define TRIGGER_TYPE_LEVEL_MASK (TRIGGER_TYPE_ROW)
+#define TRIGGER_TYPE_STATEMENT 0
+
+/* Note bits within TRIGGER_TYPE_TIMING_MASK aren't adjacent */
+#define TRIGGER_TYPE_TIMING_MASK \
+ (TRIGGER_TYPE_BEFORE | TRIGGER_TYPE_INSTEAD)
+#define TRIGGER_TYPE_AFTER 0
+
+#define TRIGGER_TYPE_EVENT_MASK \
+ (TRIGGER_TYPE_INSERT | TRIGGER_TYPE_DELETE | TRIGGER_TYPE_UPDATE | TRIGGER_TYPE_TRUNCATE)
+
+/* Macros for manipulating tgtype */
+#define TRIGGER_CLEAR_TYPE(type) ((type) = 0)
+
+#define TRIGGER_SETT_ROW(type) ((type) |= TRIGGER_TYPE_ROW)
+#define TRIGGER_SETT_STATEMENT(type) ((type) |= TRIGGER_TYPE_STATEMENT)
+#define TRIGGER_SETT_BEFORE(type) ((type) |= TRIGGER_TYPE_BEFORE)
+#define TRIGGER_SETT_AFTER(type) ((type) |= TRIGGER_TYPE_AFTER)
+#define TRIGGER_SETT_INSTEAD(type) ((type) |= TRIGGER_TYPE_INSTEAD)
+#define TRIGGER_SETT_INSERT(type) ((type) |= TRIGGER_TYPE_INSERT)
+#define TRIGGER_SETT_DELETE(type) ((type) |= TRIGGER_TYPE_DELETE)
+#define TRIGGER_SETT_UPDATE(type) ((type) |= TRIGGER_TYPE_UPDATE)
+#define TRIGGER_SETT_TRUNCATE(type) ((type) |= TRIGGER_TYPE_TRUNCATE)
+
+#define TRIGGER_FOR_ROW(type) ((type) & TRIGGER_TYPE_ROW)
+#define TRIGGER_FOR_BEFORE(type) (((type) & TRIGGER_TYPE_TIMING_MASK) == TRIGGER_TYPE_BEFORE)
+#define TRIGGER_FOR_AFTER(type) (((type) & TRIGGER_TYPE_TIMING_MASK) == TRIGGER_TYPE_AFTER)
+#define TRIGGER_FOR_INSTEAD(type) (((type) & TRIGGER_TYPE_TIMING_MASK) == TRIGGER_TYPE_INSTEAD)
+#define TRIGGER_FOR_INSERT(type) ((type) & TRIGGER_TYPE_INSERT)
+#define TRIGGER_FOR_DELETE(type) ((type) & TRIGGER_TYPE_DELETE)
+#define TRIGGER_FOR_UPDATE(type) ((type) & TRIGGER_TYPE_UPDATE)
+#define TRIGGER_FOR_TRUNCATE(type) ((type) & TRIGGER_TYPE_TRUNCATE)
+
+/*
+ * Efficient macro for checking if tgtype matches a particular level
+ * (TRIGGER_TYPE_ROW or TRIGGER_TYPE_STATEMENT), timing (TRIGGER_TYPE_BEFORE,
+ * TRIGGER_TYPE_AFTER or TRIGGER_TYPE_INSTEAD), and event (TRIGGER_TYPE_INSERT,
+ * TRIGGER_TYPE_DELETE, TRIGGER_TYPE_UPDATE, or TRIGGER_TYPE_TRUNCATE). Note
+ * that a tgtype can match more than one event, but only one level or timing.
+ */
+#define TRIGGER_TYPE_MATCHES(type, level, timing, event) \
+ (((type) & (TRIGGER_TYPE_LEVEL_MASK | TRIGGER_TYPE_TIMING_MASK | (event))) == ((level) | (timing) | (event)))
+
+/*
+ * Macro to determine whether tgnewtable or tgoldtable has been specified for
+ * a trigger.
+ */
+#define TRIGGER_USES_TRANSITION_TABLE(namepointer) \
+ ((namepointer) != (char *) NULL)
+
+
+#endif /* PG_TRIGGER_D_H */
diff --git a/src/backend/catalog/pg_ts_config_d.h b/src/backend/catalog/pg_ts_config_d.h
new file mode 100644
index 0000000..7f2c933
--- /dev/null
+++ b/src/backend/catalog/pg_ts_config_d.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_config_d.h
+ * Macro definitions for pg_ts_config
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_CONFIG_D_H
+#define PG_TS_CONFIG_D_H
+
+#define TSConfigRelationId 3602
+
+#define Anum_pg_ts_config_oid 1
+#define Anum_pg_ts_config_cfgname 2
+#define Anum_pg_ts_config_cfgnamespace 3
+#define Anum_pg_ts_config_cfgowner 4
+#define Anum_pg_ts_config_cfgparser 5
+
+#define Natts_pg_ts_config 5
+
+
+#endif /* PG_TS_CONFIG_D_H */
diff --git a/src/backend/catalog/pg_ts_config_map_d.h b/src/backend/catalog/pg_ts_config_map_d.h
new file mode 100644
index 0000000..f5b7748
--- /dev/null
+++ b/src/backend/catalog/pg_ts_config_map_d.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_config_map_d.h
+ * Macro definitions for pg_ts_config_map
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_CONFIG_MAP_D_H
+#define PG_TS_CONFIG_MAP_D_H
+
+#define TSConfigMapRelationId 3603
+
+#define Anum_pg_ts_config_map_mapcfg 1
+#define Anum_pg_ts_config_map_maptokentype 2
+#define Anum_pg_ts_config_map_mapseqno 3
+#define Anum_pg_ts_config_map_mapdict 4
+
+#define Natts_pg_ts_config_map 4
+
+
+#endif /* PG_TS_CONFIG_MAP_D_H */
diff --git a/src/backend/catalog/pg_ts_dict_d.h b/src/backend/catalog/pg_ts_dict_d.h
new file mode 100644
index 0000000..d2e8382
--- /dev/null
+++ b/src/backend/catalog/pg_ts_dict_d.h
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_dict_d.h
+ * Macro definitions for pg_ts_dict
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_DICT_D_H
+#define PG_TS_DICT_D_H
+
+#define TSDictionaryRelationId 3600
+
+#define Anum_pg_ts_dict_oid 1
+#define Anum_pg_ts_dict_dictname 2
+#define Anum_pg_ts_dict_dictnamespace 3
+#define Anum_pg_ts_dict_dictowner 4
+#define Anum_pg_ts_dict_dicttemplate 5
+#define Anum_pg_ts_dict_dictinitoption 6
+
+#define Natts_pg_ts_dict 6
+
+
+#endif /* PG_TS_DICT_D_H */
diff --git a/src/backend/catalog/pg_ts_parser_d.h b/src/backend/catalog/pg_ts_parser_d.h
new file mode 100644
index 0000000..635a4e4
--- /dev/null
+++ b/src/backend/catalog/pg_ts_parser_d.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_parser_d.h
+ * Macro definitions for pg_ts_parser
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_PARSER_D_H
+#define PG_TS_PARSER_D_H
+
+#define TSParserRelationId 3601
+
+#define Anum_pg_ts_parser_oid 1
+#define Anum_pg_ts_parser_prsname 2
+#define Anum_pg_ts_parser_prsnamespace 3
+#define Anum_pg_ts_parser_prsstart 4
+#define Anum_pg_ts_parser_prstoken 5
+#define Anum_pg_ts_parser_prsend 6
+#define Anum_pg_ts_parser_prsheadline 7
+#define Anum_pg_ts_parser_prslextype 8
+
+#define Natts_pg_ts_parser 8
+
+
+#endif /* PG_TS_PARSER_D_H */
diff --git a/src/backend/catalog/pg_ts_template_d.h b/src/backend/catalog/pg_ts_template_d.h
new file mode 100644
index 0000000..1a5f8f2
--- /dev/null
+++ b/src/backend/catalog/pg_ts_template_d.h
@@ -0,0 +1,32 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_ts_template_d.h
+ * Macro definitions for pg_ts_template
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TS_TEMPLATE_D_H
+#define PG_TS_TEMPLATE_D_H
+
+#define TSTemplateRelationId 3764
+
+#define Anum_pg_ts_template_oid 1
+#define Anum_pg_ts_template_tmplname 2
+#define Anum_pg_ts_template_tmplnamespace 3
+#define Anum_pg_ts_template_tmplinit 4
+#define Anum_pg_ts_template_tmpllexize 5
+
+#define Natts_pg_ts_template 5
+
+
+#endif /* PG_TS_TEMPLATE_D_H */
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
new file mode 100644
index 0000000..cd56714
--- /dev/null
+++ b/src/backend/catalog/pg_type.c
@@ -0,0 +1,906 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_type.c
+ * routines to support manipulation of the pg_type relation
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/pg_type.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "access/xact.h"
+#include "catalog/binary_upgrade.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "commands/typecmds.h"
+#include "miscadmin.h"
+#include "parser/scansup.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+/* Potentially set by pg_upgrade_support functions */
+Oid binary_upgrade_next_pg_type_oid = InvalidOid;
+
+/* ----------------------------------------------------------------
+ * TypeShellMake
+ *
+ * This procedure inserts a "shell" tuple into the pg_type relation.
+ * The type tuple inserted has valid but dummy values, and its
+ * "typisdefined" field is false indicating it's not really defined.
+ *
+ * This is used so that a tuple exists in the catalogs. The I/O
+ * functions for the type will link to this tuple. When the full
+ * CREATE TYPE command is issued, the bogus values will be replaced
+ * with correct ones, and "typisdefined" will be set to true.
+ * ----------------------------------------------------------------
+ */
+ObjectAddress
+TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
+{
+ Relation pg_type_desc;
+ TupleDesc tupDesc;
+ int i;
+ HeapTuple tup;
+ Datum values[Natts_pg_type];
+ bool nulls[Natts_pg_type];
+ Oid typoid;
+ NameData name;
+ ObjectAddress address;
+
+ Assert(PointerIsValid(typeName));
+
+ /*
+ * open pg_type
+ */
+ pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
+ tupDesc = pg_type_desc->rd_att;
+
+ /*
+ * initialize our *nulls and *values arrays
+ */
+ for (i = 0; i < Natts_pg_type; ++i)
+ {
+ nulls[i] = false;
+ values[i] = (Datum) NULL; /* redundant, but safe */
+ }
+
+ /*
+ * initialize *values with the type name and dummy values
+ *
+ * The representational details are the same as int4 ... it doesn't really
+ * matter what they are so long as they are consistent. Also note that we
+ * give it typtype = TYPTYPE_PSEUDO as extra insurance that it won't be
+ * mistaken for a usable type.
+ */
+ namestrcpy(&name, typeName);
+ values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
+ values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
+ values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
+ values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32));
+ values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true);
+ values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO);
+ values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE);
+ values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false);
+ values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false);
+ values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM);
+ values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN);
+ values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT);
+ values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typalign - 1] = CharGetDatum(TYPALIGN_INT);
+ values[Anum_pg_type_typstorage - 1] = CharGetDatum(TYPSTORAGE_PLAIN);
+ values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false);
+ values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid);
+ values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1);
+ values[Anum_pg_type_typndims - 1] = Int32GetDatum(0);
+ values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid);
+ nulls[Anum_pg_type_typdefaultbin - 1] = true;
+ nulls[Anum_pg_type_typdefault - 1] = true;
+ nulls[Anum_pg_type_typacl - 1] = true;
+
+ /* Use binary-upgrade override for pg_type.oid? */
+ if (IsBinaryUpgrade)
+ {
+ if (!OidIsValid(binary_upgrade_next_pg_type_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("pg_type OID value not set when in binary upgrade mode")));
+
+ typoid = binary_upgrade_next_pg_type_oid;
+ binary_upgrade_next_pg_type_oid = InvalidOid;
+ }
+ else
+ {
+ typoid = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId,
+ Anum_pg_type_oid);
+ }
+
+ values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typoid);
+
+ /*
+ * create a new type tuple
+ */
+ tup = heap_form_tuple(tupDesc, values, nulls);
+
+ /*
+ * insert the tuple in the relation and get the tuple's oid.
+ */
+ CatalogTupleInsert(pg_type_desc, tup);
+
+ /*
+ * Create dependencies. We can/must skip this in bootstrap mode.
+ */
+ if (!IsBootstrapProcessingMode())
+ GenerateTypeDependencies(tup,
+ pg_type_desc,
+ NULL,
+ NULL,
+ 0,
+ false,
+ false,
+ false);
+
+ /* Post creation hook for new shell type */
+ InvokeObjectPostCreateHook(TypeRelationId, typoid, 0);
+
+ ObjectAddressSet(address, TypeRelationId, typoid);
+
+ /*
+ * clean up and return the type-oid
+ */
+ heap_freetuple(tup);
+ table_close(pg_type_desc, RowExclusiveLock);
+
+ return address;
+}
+
+/* ----------------------------------------------------------------
+ * TypeCreate
+ *
+ * This does all the necessary work needed to define a new type.
+ *
+ * Returns the ObjectAddress assigned to the new type.
+ * If newTypeOid is zero (the normal case), a new OID is created;
+ * otherwise we use exactly that OID.
+ * ----------------------------------------------------------------
+ */
+ObjectAddress
+TypeCreate(Oid newTypeOid,
+ const char *typeName,
+ Oid typeNamespace,
+ Oid relationOid, /* only for relation rowtypes */
+ char relationKind, /* ditto */
+ Oid ownerId,
+ int16 internalSize,
+ char typeType,
+ char typeCategory,
+ bool typePreferred,
+ char typDelim,
+ Oid inputProcedure,
+ Oid outputProcedure,
+ Oid receiveProcedure,
+ Oid sendProcedure,
+ Oid typmodinProcedure,
+ Oid typmodoutProcedure,
+ Oid analyzeProcedure,
+ Oid elementType,
+ bool isImplicitArray,
+ Oid arrayType,
+ Oid baseType,
+ const char *defaultTypeValue, /* human readable rep */
+ char *defaultTypeBin, /* cooked rep */
+ bool passedByValue,
+ char alignment,
+ char storage,
+ int32 typeMod,
+ int32 typNDims, /* Array dimensions for baseType */
+ bool typeNotNull,
+ Oid typeCollation)
+{
+ Relation pg_type_desc;
+ Oid typeObjectId;
+ bool isDependentType;
+ bool rebuildDeps = false;
+ Acl *typacl;
+ HeapTuple tup;
+ bool nulls[Natts_pg_type];
+ bool replaces[Natts_pg_type];
+ Datum values[Natts_pg_type];
+ NameData name;
+ int i;
+ ObjectAddress address;
+
+ /*
+ * We assume that the caller validated the arguments individually, but did
+ * not check for bad combinations.
+ *
+ * Validate size specifications: either positive (fixed-length) or -1
+ * (varlena) or -2 (cstring).
+ */
+ if (!(internalSize > 0 ||
+ internalSize == -1 ||
+ internalSize == -2))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("invalid type internal size %d",
+ internalSize)));
+
+ if (passedByValue)
+ {
+ /*
+ * Pass-by-value types must have a fixed length that is one of the
+ * values supported by fetch_att() and store_att_byval(); and the
+ * alignment had better agree, too. All this code must match
+ * access/tupmacs.h!
+ */
+ if (internalSize == (int16) sizeof(char))
+ {
+ if (alignment != TYPALIGN_CHAR)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
+ alignment, internalSize)));
+ }
+ else if (internalSize == (int16) sizeof(int16))
+ {
+ if (alignment != TYPALIGN_SHORT)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
+ alignment, internalSize)));
+ }
+ else if (internalSize == (int16) sizeof(int32))
+ {
+ if (alignment != TYPALIGN_INT)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
+ alignment, internalSize)));
+ }
+#if SIZEOF_DATUM == 8
+ else if (internalSize == (int16) sizeof(Datum))
+ {
+ if (alignment != TYPALIGN_DOUBLE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
+ alignment, internalSize)));
+ }
+#endif
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("internal size %d is invalid for passed-by-value type",
+ internalSize)));
+ }
+ else
+ {
+ /* varlena types must have int align or better */
+ if (internalSize == -1 &&
+ !(alignment == TYPALIGN_INT || alignment == TYPALIGN_DOUBLE))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("alignment \"%c\" is invalid for variable-length type",
+ alignment)));
+ /* cstring must have char alignment */
+ if (internalSize == -2 && !(alignment == TYPALIGN_CHAR))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("alignment \"%c\" is invalid for variable-length type",
+ alignment)));
+ }
+
+ /* Only varlena types can be toasted */
+ if (storage != TYPSTORAGE_PLAIN && internalSize != -1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("fixed-size types must have storage PLAIN")));
+
+ /*
+ * This is a dependent type if it's an implicitly-created array type, or
+ * if it's a relation rowtype that's not a composite type. For such types
+ * we'll leave the ACL empty, and we'll skip creating some dependency
+ * records because there will be a dependency already through the
+ * depended-on type or relation. (Caution: this is closely intertwined
+ * with some behavior in GenerateTypeDependencies.)
+ */
+ isDependentType = isImplicitArray ||
+ (OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE);
+
+ /*
+ * initialize arrays needed for heap_form_tuple or heap_modify_tuple
+ */
+ for (i = 0; i < Natts_pg_type; ++i)
+ {
+ nulls[i] = false;
+ replaces[i] = true;
+ values[i] = (Datum) 0;
+ }
+
+ /*
+ * insert data values
+ */
+ namestrcpy(&name, typeName);
+ values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
+ values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
+ values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
+ values[Anum_pg_type_typlen - 1] = Int16GetDatum(internalSize);
+ values[Anum_pg_type_typbyval - 1] = BoolGetDatum(passedByValue);
+ values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType);
+ values[Anum_pg_type_typcategory - 1] = CharGetDatum(typeCategory);
+ values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(typePreferred);
+ values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(true);
+ values[Anum_pg_type_typdelim - 1] = CharGetDatum(typDelim);
+ values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(relationOid);
+ values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(elementType);
+ values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(arrayType);
+ values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(inputProcedure);
+ values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(outputProcedure);
+ values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(receiveProcedure);
+ values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(sendProcedure);
+ values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(typmodinProcedure);
+ values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(typmodoutProcedure);
+ values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(analyzeProcedure);
+ values[Anum_pg_type_typalign - 1] = CharGetDatum(alignment);
+ values[Anum_pg_type_typstorage - 1] = CharGetDatum(storage);
+ values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(typeNotNull);
+ values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(baseType);
+ values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(typeMod);
+ values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims);
+ values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation);
+
+ /*
+ * initialize the default binary value for this type. Check for nulls of
+ * course.
+ */
+ if (defaultTypeBin)
+ values[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(defaultTypeBin);
+ else
+ nulls[Anum_pg_type_typdefaultbin - 1] = true;
+
+ /*
+ * initialize the default value for this type.
+ */
+ if (defaultTypeValue)
+ values[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultTypeValue);
+ else
+ nulls[Anum_pg_type_typdefault - 1] = true;
+
+ /*
+ * Initialize the type's ACL, too. But dependent types don't get one.
+ */
+ if (isDependentType)
+ typacl = NULL;
+ else
+ typacl = get_user_default_acl(OBJECT_TYPE, ownerId,
+ typeNamespace);
+ if (typacl != NULL)
+ values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl);
+ else
+ nulls[Anum_pg_type_typacl - 1] = true;
+
+ /*
+ * open pg_type and prepare to insert or update a row.
+ *
+ * NOTE: updating will not work correctly in bootstrap mode; but we don't
+ * expect to be overwriting any shell types in bootstrap mode.
+ */
+ pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
+
+ tup = SearchSysCacheCopy2(TYPENAMENSP,
+ CStringGetDatum(typeName),
+ ObjectIdGetDatum(typeNamespace));
+ if (HeapTupleIsValid(tup))
+ {
+ Form_pg_type typform = (Form_pg_type) GETSTRUCT(tup);
+
+ /*
+ * check that the type is not already defined. It may exist as a
+ * shell type, however.
+ */
+ if (typform->typisdefined)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("type \"%s\" already exists", typeName)));
+
+ /*
+ * shell type must have been created by same owner
+ */
+ if (typform->typowner != ownerId)
+ aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TYPE, typeName);
+
+ /* trouble if caller wanted to force the OID */
+ if (OidIsValid(newTypeOid))
+ elog(ERROR, "cannot assign new OID to existing shell type");
+
+ replaces[Anum_pg_type_oid - 1] = false;
+
+ /*
+ * Okay to update existing shell type tuple
+ */
+ tup = heap_modify_tuple(tup,
+ RelationGetDescr(pg_type_desc),
+ values,
+ nulls,
+ replaces);
+
+ CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup);
+
+ typeObjectId = typform->oid;
+
+ rebuildDeps = true; /* get rid of shell type's dependencies */
+ }
+ else
+ {
+ /* Force the OID if requested by caller */
+ if (OidIsValid(newTypeOid))
+ typeObjectId = newTypeOid;
+ /* Use binary-upgrade override for pg_type.oid, if supplied. */
+ else if (IsBinaryUpgrade)
+ {
+ if (!OidIsValid(binary_upgrade_next_pg_type_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("pg_type OID value not set when in binary upgrade mode")));
+
+ typeObjectId = binary_upgrade_next_pg_type_oid;
+ binary_upgrade_next_pg_type_oid = InvalidOid;
+ }
+ else
+ {
+ typeObjectId = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId,
+ Anum_pg_type_oid);
+ }
+
+ values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typeObjectId);
+
+ tup = heap_form_tuple(RelationGetDescr(pg_type_desc),
+ values, nulls);
+
+ CatalogTupleInsert(pg_type_desc, tup);
+ }
+
+ /*
+ * Create dependencies. We can/must skip this in bootstrap mode.
+ */
+ if (!IsBootstrapProcessingMode())
+ GenerateTypeDependencies(tup,
+ pg_type_desc,
+ (defaultTypeBin ?
+ stringToNode(defaultTypeBin) :
+ NULL),
+ typacl,
+ relationKind,
+ isImplicitArray,
+ isDependentType,
+ rebuildDeps);
+
+ /* Post creation hook for new type */
+ InvokeObjectPostCreateHook(TypeRelationId, typeObjectId, 0);
+
+ ObjectAddressSet(address, TypeRelationId, typeObjectId);
+
+ /*
+ * finish up
+ */
+ table_close(pg_type_desc, RowExclusiveLock);
+
+ return address;
+}
+
+/*
+ * GenerateTypeDependencies: build the dependencies needed for a type
+ *
+ * Most of what this function needs to know about the type is passed as the
+ * new pg_type row, typeTuple. We make callers pass the pg_type Relation
+ * as well, so that we have easy access to a tuple descriptor for the row.
+ *
+ * While this is able to extract the defaultExpr and typacl from the tuple,
+ * doing so is relatively expensive, and callers may have those values at
+ * hand already. Pass those if handy, otherwise pass NULL. (typacl is really
+ * "Acl *", but we declare it "void *" to avoid including acl.h in pg_type.h.)
+ *
+ * relationKind and isImplicitArray are likewise somewhat expensive to deduce
+ * from the tuple, so we make callers pass those (they're not optional).
+ *
+ * isDependentType is true if this is an implicit array or relation rowtype;
+ * that means it doesn't need its own dependencies on owner etc.
+ *
+ * If rebuild is true, we remove existing dependencies and rebuild them
+ * from scratch. This is needed for ALTER TYPE, and also when replacing
+ * a shell type. We don't remove an existing extension dependency, though.
+ * (That means an extension can't absorb a shell type created in another
+ * extension, nor ALTER a type created by another extension. Also, if it
+ * replaces a free-standing shell type or ALTERs a free-standing type,
+ * that type will become a member of the extension.)
+ */
+void
+GenerateTypeDependencies(HeapTuple typeTuple,
+ Relation typeCatalog,
+ Node *defaultExpr,
+ void *typacl,
+ char relationKind, /* only for relation rowtypes */
+ bool isImplicitArray,
+ bool isDependentType,
+ bool rebuild)
+{
+ Form_pg_type typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
+ Oid typeObjectId = typeForm->oid;
+ Datum datum;
+ bool isNull;
+ ObjectAddress myself,
+ referenced;
+
+ /* Extract defaultExpr if caller didn't pass it */
+ if (defaultExpr == NULL)
+ {
+ datum = heap_getattr(typeTuple, Anum_pg_type_typdefaultbin,
+ RelationGetDescr(typeCatalog), &isNull);
+ if (!isNull)
+ defaultExpr = stringToNode(TextDatumGetCString(datum));
+ }
+ /* Extract typacl if caller didn't pass it */
+ if (typacl == NULL)
+ {
+ datum = heap_getattr(typeTuple, Anum_pg_type_typacl,
+ RelationGetDescr(typeCatalog), &isNull);
+ if (!isNull)
+ typacl = DatumGetAclPCopy(datum);
+ }
+
+ /* If rebuild, first flush old dependencies, except extension deps */
+ if (rebuild)
+ {
+ deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
+ deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
+ }
+
+ myself.classId = TypeRelationId;
+ myself.objectId = typeObjectId;
+ myself.objectSubId = 0;
+
+ /*
+ * Make dependencies on namespace, owner, ACL, extension.
+ *
+ * Skip these for a dependent type, since it will have such dependencies
+ * indirectly through its depended-on type or relation.
+ */
+ if (!isDependentType)
+ {
+ referenced.classId = NamespaceRelationId;
+ referenced.objectId = typeForm->typnamespace;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ recordDependencyOnOwner(TypeRelationId, typeObjectId,
+ typeForm->typowner);
+
+ recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
+ typeForm->typowner, typacl);
+
+ recordDependencyOnCurrentExtension(&myself, rebuild);
+ }
+
+ /* Normal dependencies on the I/O functions */
+ if (OidIsValid(typeForm->typinput))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = typeForm->typinput;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(typeForm->typoutput))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = typeForm->typoutput;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(typeForm->typreceive))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = typeForm->typreceive;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(typeForm->typsend))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = typeForm->typsend;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(typeForm->typmodin))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = typeForm->typmodin;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(typeForm->typmodout))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = typeForm->typmodout;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(typeForm->typanalyze))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = typeForm->typanalyze;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /*
+ * If the type is a rowtype for a relation, mark it as internally
+ * dependent on the relation, *unless* it is a stand-alone composite type
+ * relation. For the latter case, we have to reverse the dependency.
+ *
+ * In the former case, this allows the type to be auto-dropped when the
+ * relation is, and not otherwise. And in the latter, of course we get the
+ * opposite effect.
+ */
+ if (OidIsValid(typeForm->typrelid))
+ {
+ referenced.classId = RelationRelationId;
+ referenced.objectId = typeForm->typrelid;
+ referenced.objectSubId = 0;
+
+ if (relationKind != RELKIND_COMPOSITE_TYPE)
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+ else
+ recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
+ }
+
+ /*
+ * If the type is an implicitly-created array type, mark it as internally
+ * dependent on the element type. Otherwise, if it has an element type,
+ * the dependency is a normal one.
+ */
+ if (OidIsValid(typeForm->typelem))
+ {
+ referenced.classId = TypeRelationId;
+ referenced.objectId = typeForm->typelem;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced,
+ isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
+ }
+
+ /* Normal dependency from a domain to its base type. */
+ if (OidIsValid(typeForm->typbasetype))
+ {
+ referenced.classId = TypeRelationId;
+ referenced.objectId = typeForm->typbasetype;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Normal dependency from a domain to its collation. */
+ /* We know the default collation is pinned, so don't bother recording it */
+ if (OidIsValid(typeForm->typcollation) &&
+ typeForm->typcollation != DEFAULT_COLLATION_OID)
+ {
+ referenced.classId = CollationRelationId;
+ referenced.objectId = typeForm->typcollation;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ /* Normal dependency on the default expression. */
+ if (defaultExpr)
+ recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
+}
+
+/*
+ * RenameTypeInternal
+ * This renames a type, as well as any associated array type.
+ *
+ * Caller must have already checked privileges.
+ *
+ * Currently this is used for renaming table rowtypes and for
+ * ALTER TYPE RENAME TO command.
+ */
+void
+RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
+{
+ Relation pg_type_desc;
+ HeapTuple tuple;
+ Form_pg_type typ;
+ Oid arrayOid;
+ Oid oldTypeOid;
+
+ pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for type %u", typeOid);
+ typ = (Form_pg_type) GETSTRUCT(tuple);
+
+ /* We are not supposed to be changing schemas here */
+ Assert(typeNamespace == typ->typnamespace);
+
+ arrayOid = typ->typarray;
+
+ /* Check for a conflicting type name. */
+ oldTypeOid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
+ CStringGetDatum(newTypeName),
+ ObjectIdGetDatum(typeNamespace));
+
+ /*
+ * If there is one, see if it's an autogenerated array type, and if so
+ * rename it out of the way. (But we must skip that for a shell type
+ * because moveArrayTypeName will do the wrong thing in that case.)
+ * Otherwise, we can at least give a more friendly error than unique-index
+ * violation.
+ */
+ if (OidIsValid(oldTypeOid))
+ {
+ if (get_typisdefined(oldTypeOid) &&
+ moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
+ /* successfully dodged the problem */ ;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("type \"%s\" already exists", newTypeName)));
+ }
+
+ /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
+ namestrcpy(&(typ->typname), newTypeName);
+
+ CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
+
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
+ heap_freetuple(tuple);
+ table_close(pg_type_desc, RowExclusiveLock);
+
+ /*
+ * If the type has an array type, recurse to handle that. But we don't
+ * need to do anything more if we already renamed that array type above
+ * (which would happen when, eg, renaming "foo" to "_foo").
+ */
+ if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
+ {
+ char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
+
+ RenameTypeInternal(arrayOid, arrname, typeNamespace);
+ pfree(arrname);
+ }
+}
+
+
+/*
+ * makeArrayTypeName
+ * - given a base type name, make an array type name for it
+ *
+ * the caller is responsible for pfreeing the result
+ */
+char *
+makeArrayTypeName(const char *typeName, Oid typeNamespace)
+{
+ char *arr = (char *) palloc(NAMEDATALEN);
+ int namelen = strlen(typeName);
+ int i;
+
+ /*
+ * The idea is to prepend underscores as needed until we make a name that
+ * doesn't collide with anything...
+ */
+ for (i = 1; i < NAMEDATALEN - 1; i++)
+ {
+ arr[i - 1] = '_';
+ if (i + namelen < NAMEDATALEN)
+ strcpy(arr + i, typeName);
+ else
+ {
+ memcpy(arr + i, typeName, NAMEDATALEN - i);
+ truncate_identifier(arr, NAMEDATALEN, false);
+ }
+ if (!SearchSysCacheExists2(TYPENAMENSP,
+ CStringGetDatum(arr),
+ ObjectIdGetDatum(typeNamespace)))
+ break;
+ }
+
+ if (i >= NAMEDATALEN - 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("could not form array type name for type \"%s\"",
+ typeName)));
+
+ return arr;
+}
+
+
+/*
+ * moveArrayTypeName
+ * - try to reassign an array type name that the user wants to use.
+ *
+ * The given type name has been discovered to already exist (with the given
+ * OID). If it is an autogenerated array type, change the array type's name
+ * to not conflict. This allows the user to create type "foo" followed by
+ * type "_foo" without problems. (Of course, there are race conditions if
+ * two backends try to create similarly-named types concurrently, but the
+ * worst that can happen is an unnecessary failure --- anything we do here
+ * will be rolled back if the type creation fails due to conflicting names.)
+ *
+ * Note that this must be called *before* calling makeArrayTypeName to
+ * determine the new type's own array type name; else the latter will
+ * certainly pick the same name.
+ *
+ * Returns true if successfully moved the type, false if not.
+ *
+ * We also return true if the given type is a shell type. In this case
+ * the type has not been renamed out of the way, but nonetheless it can
+ * be expected that TypeCreate will succeed. This behavior is convenient
+ * for most callers --- those that need to distinguish the shell-type case
+ * must do their own typisdefined test.
+ */
+bool
+moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
+{
+ Oid elemOid;
+ char *newname;
+
+ /* We need do nothing if it's a shell type. */
+ if (!get_typisdefined(typeOid))
+ return true;
+
+ /* Can't change it if it's not an autogenerated array type. */
+ elemOid = get_element_type(typeOid);
+ if (!OidIsValid(elemOid) ||
+ get_array_type(elemOid) != typeOid)
+ return false;
+
+ /*
+ * OK, use makeArrayTypeName to pick an unused modification of the name.
+ * Note that since makeArrayTypeName is an iterative process, this will
+ * produce a name that it might have produced the first time, had the
+ * conflicting type we are about to create already existed.
+ */
+ newname = makeArrayTypeName(typeName, typeNamespace);
+
+ /* Apply the rename */
+ RenameTypeInternal(typeOid, newname, typeNamespace);
+
+ /*
+ * We must bump the command counter so that any subsequent use of
+ * makeArrayTypeName sees what we just did and doesn't pick the same name.
+ */
+ CommandCounterIncrement();
+
+ pfree(newname);
+
+ return true;
+}
diff --git a/src/backend/catalog/pg_type_d.h b/src/backend/catalog/pg_type_d.h
new file mode 100644
index 0000000..d967a69
--- /dev/null
+++ b/src/backend/catalog/pg_type_d.h
@@ -0,0 +1,285 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_type_d.h
+ * Macro definitions for pg_type
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_TYPE_D_H
+#define PG_TYPE_D_H
+
+#define TypeRelationId 1247
+#define TypeRelation_Rowtype_Id 71
+
+#define Anum_pg_type_oid 1
+#define Anum_pg_type_typname 2
+#define Anum_pg_type_typnamespace 3
+#define Anum_pg_type_typowner 4
+#define Anum_pg_type_typlen 5
+#define Anum_pg_type_typbyval 6
+#define Anum_pg_type_typtype 7
+#define Anum_pg_type_typcategory 8
+#define Anum_pg_type_typispreferred 9
+#define Anum_pg_type_typisdefined 10
+#define Anum_pg_type_typdelim 11
+#define Anum_pg_type_typrelid 12
+#define Anum_pg_type_typelem 13
+#define Anum_pg_type_typarray 14
+#define Anum_pg_type_typinput 15
+#define Anum_pg_type_typoutput 16
+#define Anum_pg_type_typreceive 17
+#define Anum_pg_type_typsend 18
+#define Anum_pg_type_typmodin 19
+#define Anum_pg_type_typmodout 20
+#define Anum_pg_type_typanalyze 21
+#define Anum_pg_type_typalign 22
+#define Anum_pg_type_typstorage 23
+#define Anum_pg_type_typnotnull 24
+#define Anum_pg_type_typbasetype 25
+#define Anum_pg_type_typtypmod 26
+#define Anum_pg_type_typndims 27
+#define Anum_pg_type_typcollation 28
+#define Anum_pg_type_typdefaultbin 29
+#define Anum_pg_type_typdefault 30
+#define Anum_pg_type_typacl 31
+
+#define Natts_pg_type 31
+
+
+/*
+ * macros for values of poor-mans-enumerated-type columns
+ */
+#define TYPTYPE_BASE 'b' /* base type (ordinary scalar type) */
+#define TYPTYPE_COMPOSITE 'c' /* composite (e.g., table's rowtype) */
+#define TYPTYPE_DOMAIN 'd' /* domain over another type */
+#define TYPTYPE_ENUM 'e' /* enumerated type */
+#define TYPTYPE_PSEUDO 'p' /* pseudo-type */
+#define TYPTYPE_RANGE 'r' /* range type */
+
+#define TYPCATEGORY_INVALID '\0' /* not an allowed category */
+#define TYPCATEGORY_ARRAY 'A'
+#define TYPCATEGORY_BOOLEAN 'B'
+#define TYPCATEGORY_COMPOSITE 'C'
+#define TYPCATEGORY_DATETIME 'D'
+#define TYPCATEGORY_ENUM 'E'
+#define TYPCATEGORY_GEOMETRIC 'G'
+#define TYPCATEGORY_NETWORK 'I' /* think INET */
+#define TYPCATEGORY_NUMERIC 'N'
+#define TYPCATEGORY_PSEUDOTYPE 'P'
+#define TYPCATEGORY_RANGE 'R'
+#define TYPCATEGORY_STRING 'S'
+#define TYPCATEGORY_TIMESPAN 'T'
+#define TYPCATEGORY_USER 'U'
+#define TYPCATEGORY_BITSTRING 'V' /* er ... "varbit"? */
+#define TYPCATEGORY_UNKNOWN 'X'
+
+#define TYPALIGN_CHAR 'c' /* char alignment (i.e. unaligned) */
+#define TYPALIGN_SHORT 's' /* short alignment (typically 2 bytes) */
+#define TYPALIGN_INT 'i' /* int alignment (typically 4 bytes) */
+#define TYPALIGN_DOUBLE 'd' /* double alignment (often 8 bytes) */
+
+#define TYPSTORAGE_PLAIN 'p' /* type not prepared for toasting */
+#define TYPSTORAGE_EXTERNAL 'e' /* toastable, don't try to compress */
+#define TYPSTORAGE_EXTENDED 'x' /* fully toastable */
+#define TYPSTORAGE_MAIN 'm' /* like 'x' but try to store inline */
+
+/* Is a type OID a polymorphic pseudotype? (Beware of multiple evaluation) */
+#define IsPolymorphicType(typid) \
+ (IsPolymorphicTypeFamily1(typid) || \
+ IsPolymorphicTypeFamily2(typid))
+
+/* Code not part of polymorphic type resolution should not use these macros: */
+#define IsPolymorphicTypeFamily1(typid) \
+ ((typid) == ANYELEMENTOID || \
+ (typid) == ANYARRAYOID || \
+ (typid) == ANYNONARRAYOID || \
+ (typid) == ANYENUMOID || \
+ (typid) == ANYRANGEOID)
+
+#define IsPolymorphicTypeFamily2(typid) \
+ ((typid) == ANYCOMPATIBLEOID || \
+ (typid) == ANYCOMPATIBLEARRAYOID || \
+ (typid) == ANYCOMPATIBLENONARRAYOID || \
+ (typid) == ANYCOMPATIBLERANGEOID)
+
+#define BOOLOID 16
+#define BYTEAOID 17
+#define CHAROID 18
+#define NAMEOID 19
+#define INT8OID 20
+#define INT2OID 21
+#define INT2VECTOROID 22
+#define INT4OID 23
+#define REGPROCOID 24
+#define TEXTOID 25
+#define OIDOID 26
+#define TIDOID 27
+#define XIDOID 28
+#define CIDOID 29
+#define OIDVECTOROID 30
+#define JSONOID 114
+#define XMLOID 142
+#define PGNODETREEOID 194
+#define PGNDISTINCTOID 3361
+#define PGDEPENDENCIESOID 3402
+#define PGMCVLISTOID 5017
+#define PGDDLCOMMANDOID 32
+#define XID8OID 5069
+#define POINTOID 600
+#define LSEGOID 601
+#define PATHOID 602
+#define BOXOID 603
+#define POLYGONOID 604
+#define LINEOID 628
+#define FLOAT4OID 700
+#define FLOAT8OID 701
+#define UNKNOWNOID 705
+#define CIRCLEOID 718
+#define CASHOID 790
+#define MACADDROID 829
+#define INETOID 869
+#define CIDROID 650
+#define MACADDR8OID 774
+#define ACLITEMOID 1033
+#define BPCHAROID 1042
+#define VARCHAROID 1043
+#define DATEOID 1082
+#define TIMEOID 1083
+#define TIMESTAMPOID 1114
+#define TIMESTAMPTZOID 1184
+#define INTERVALOID 1186
+#define TIMETZOID 1266
+#define BITOID 1560
+#define VARBITOID 1562
+#define NUMERICOID 1700
+#define REFCURSOROID 1790
+#define REGPROCEDUREOID 2202
+#define REGOPEROID 2203
+#define REGOPERATOROID 2204
+#define REGCLASSOID 2205
+#define REGCOLLATIONOID 4191
+#define REGTYPEOID 2206
+#define REGROLEOID 4096
+#define REGNAMESPACEOID 4089
+#define UUIDOID 2950
+#define LSNOID 3220
+#define TSVECTOROID 3614
+#define GTSVECTOROID 3642
+#define TSQUERYOID 3615
+#define REGCONFIGOID 3734
+#define REGDICTIONARYOID 3769
+#define JSONBOID 3802
+#define JSONPATHOID 4072
+#define TXID_SNAPSHOTOID 2970
+#define PG_SNAPSHOTOID 5038
+#define INT4RANGEOID 3904
+#define NUMRANGEOID 3906
+#define TSRANGEOID 3908
+#define TSTZRANGEOID 3910
+#define DATERANGEOID 3912
+#define INT8RANGEOID 3926
+#define RECORDOID 2249
+#define RECORDARRAYOID 2287
+#define CSTRINGOID 2275
+#define ANYOID 2276
+#define ANYARRAYOID 2277
+#define VOIDOID 2278
+#define TRIGGEROID 2279
+#define EVTTRIGGEROID 3838
+#define LANGUAGE_HANDLEROID 2280
+#define INTERNALOID 2281
+#define ANYELEMENTOID 2283
+#define ANYNONARRAYOID 2776
+#define ANYENUMOID 3500
+#define FDW_HANDLEROID 3115
+#define INDEX_AM_HANDLEROID 325
+#define TSM_HANDLEROID 3310
+#define TABLE_AM_HANDLEROID 269
+#define ANYRANGEOID 3831
+#define ANYCOMPATIBLEOID 5077
+#define ANYCOMPATIBLEARRAYOID 5078
+#define ANYCOMPATIBLENONARRAYOID 5079
+#define ANYCOMPATIBLERANGEOID 5080
+#define BOOLARRAYOID 1000
+#define BYTEAARRAYOID 1001
+#define CHARARRAYOID 1002
+#define NAMEARRAYOID 1003
+#define INT8ARRAYOID 1016
+#define INT2ARRAYOID 1005
+#define INT2VECTORARRAYOID 1006
+#define INT4ARRAYOID 1007
+#define REGPROCARRAYOID 1008
+#define TEXTARRAYOID 1009
+#define OIDARRAYOID 1028
+#define TIDARRAYOID 1010
+#define XIDARRAYOID 1011
+#define CIDARRAYOID 1012
+#define OIDVECTORARRAYOID 1013
+#define JSONARRAYOID 199
+#define XMLARRAYOID 143
+#define XID8ARRAYOID 271
+#define POINTARRAYOID 1017
+#define LSEGARRAYOID 1018
+#define PATHARRAYOID 1019
+#define BOXARRAYOID 1020
+#define POLYGONARRAYOID 1027
+#define LINEARRAYOID 629
+#define FLOAT4ARRAYOID 1021
+#define FLOAT8ARRAYOID 1022
+#define CIRCLEARRAYOID 719
+#define MONEYARRAYOID 791
+#define MACADDRARRAYOID 1040
+#define INETARRAYOID 1041
+#define CIDRARRAYOID 651
+#define MACADDR8ARRAYOID 775
+#define ACLITEMARRAYOID 1034
+#define BPCHARARRAYOID 1014
+#define VARCHARARRAYOID 1015
+#define DATEARRAYOID 1182
+#define TIMEARRAYOID 1183
+#define TIMESTAMPARRAYOID 1115
+#define TIMESTAMPTZARRAYOID 1185
+#define INTERVALARRAYOID 1187
+#define TIMETZARRAYOID 1270
+#define BITARRAYOID 1561
+#define VARBITARRAYOID 1563
+#define NUMERICARRAYOID 1231
+#define REFCURSORARRAYOID 2201
+#define REGPROCEDUREARRAYOID 2207
+#define REGOPERARRAYOID 2208
+#define REGOPERATORARRAYOID 2209
+#define REGCLASSARRAYOID 2210
+#define REGCOLLATIONARRAYOID 4192
+#define REGTYPEARRAYOID 2211
+#define REGROLEARRAYOID 4097
+#define REGNAMESPACEARRAYOID 4090
+#define UUIDARRAYOID 2951
+#define PG_LSNARRAYOID 3221
+#define TSVECTORARRAYOID 3643
+#define GTSVECTORARRAYOID 3644
+#define TSQUERYARRAYOID 3645
+#define REGCONFIGARRAYOID 3735
+#define REGDICTIONARYARRAYOID 3770
+#define JSONBARRAYOID 3807
+#define JSONPATHARRAYOID 4073
+#define TXID_SNAPSHOTARRAYOID 2949
+#define PG_SNAPSHOTARRAYOID 5039
+#define INT4RANGEARRAYOID 3905
+#define NUMRANGEARRAYOID 3907
+#define TSRANGEARRAYOID 3909
+#define TSTZRANGEARRAYOID 3911
+#define DATERANGEARRAYOID 3913
+#define INT8RANGEARRAYOID 3927
+#define CSTRINGARRAYOID 1263
+
+#endif /* PG_TYPE_D_H */
diff --git a/src/backend/catalog/pg_user_mapping_d.h b/src/backend/catalog/pg_user_mapping_d.h
new file mode 100644
index 0000000..48bea90
--- /dev/null
+++ b/src/backend/catalog/pg_user_mapping_d.h
@@ -0,0 +1,31 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_user_mapping_d.h
+ * Macro definitions for pg_user_mapping
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_USER_MAPPING_D_H
+#define PG_USER_MAPPING_D_H
+
+#define UserMappingRelationId 1418
+
+#define Anum_pg_user_mapping_oid 1
+#define Anum_pg_user_mapping_umuser 2
+#define Anum_pg_user_mapping_umserver 3
+#define Anum_pg_user_mapping_umoptions 4
+
+#define Natts_pg_user_mapping 4
+
+
+#endif /* PG_USER_MAPPING_D_H */
diff --git a/src/backend/catalog/postgres.bki b/src/backend/catalog/postgres.bki
new file mode 100644
index 0000000..4badf4d
--- /dev/null
+++ b/src/backend/catalog/postgres.bki
@@ -0,0 +1,10432 @@
+# PostgreSQL 13
+create pg_proc 1255 bootstrap rowtype_oid 81
+ (
+ oid = oid ,
+ proname = name ,
+ pronamespace = oid ,
+ proowner = oid ,
+ prolang = oid ,
+ procost = float4 ,
+ prorows = float4 ,
+ provariadic = oid ,
+ prosupport = regproc ,
+ prokind = char ,
+ prosecdef = bool ,
+ proleakproof = bool ,
+ proisstrict = bool ,
+ proretset = bool ,
+ provolatile = char ,
+ proparallel = char ,
+ pronargs = int2 ,
+ pronargdefaults = int2 ,
+ prorettype = oid ,
+ proargtypes = oidvector ,
+ proallargtypes = _oid ,
+ proargmodes = _char ,
+ proargnames = _text ,
+ proargdefaults = pg_node_tree ,
+ protrftypes = _oid ,
+ prosrc = text FORCE NOT NULL ,
+ probin = text ,
+ proconfig = _text ,
+ proacl = _aclitem
+ )
+insert ( 1242 boolin 11 10 12 1 0 0 0 f f f t f i s 1 0 16 2275 _null_ _null_ _null_ _null_ _null_ boolin _null_ _null_ _null_ )
+insert ( 1243 boolout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 16 _null_ _null_ _null_ _null_ _null_ boolout _null_ _null_ _null_ )
+insert ( 1244 byteain 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2275 _null_ _null_ _null_ _null_ _null_ byteain _null_ _null_ _null_ )
+insert ( 31 byteaout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 17 _null_ _null_ _null_ _null_ _null_ byteaout _null_ _null_ _null_ )
+insert ( 1245 charin 11 10 12 1 0 0 0 f f f t f i s 1 0 18 2275 _null_ _null_ _null_ _null_ _null_ charin _null_ _null_ _null_ )
+insert ( 33 charout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 18 _null_ _null_ _null_ _null_ _null_ charout _null_ _null_ _null_ )
+insert ( 34 namein 11 10 12 1 0 0 0 f f f t f i s 1 0 19 2275 _null_ _null_ _null_ _null_ _null_ namein _null_ _null_ _null_ )
+insert ( 35 nameout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 19 _null_ _null_ _null_ _null_ _null_ nameout _null_ _null_ _null_ )
+insert ( 38 int2in 11 10 12 1 0 0 0 f f f t f i s 1 0 21 2275 _null_ _null_ _null_ _null_ _null_ int2in _null_ _null_ _null_ )
+insert ( 39 int2out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 21 _null_ _null_ _null_ _null_ _null_ int2out _null_ _null_ _null_ )
+insert ( 40 int2vectorin 11 10 12 1 0 0 0 f f f t f i s 1 0 22 2275 _null_ _null_ _null_ _null_ _null_ int2vectorin _null_ _null_ _null_ )
+insert ( 41 int2vectorout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 22 _null_ _null_ _null_ _null_ _null_ int2vectorout _null_ _null_ _null_ )
+insert ( 42 int4in 11 10 12 1 0 0 0 f f f t f i s 1 0 23 2275 _null_ _null_ _null_ _null_ _null_ int4in _null_ _null_ _null_ )
+insert ( 43 int4out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ int4out _null_ _null_ _null_ )
+insert ( 44 regprocin 11 10 12 1 0 0 0 f f f t f s s 1 0 24 2275 _null_ _null_ _null_ _null_ _null_ regprocin _null_ _null_ _null_ )
+insert ( 45 regprocout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 24 _null_ _null_ _null_ _null_ _null_ regprocout _null_ _null_ _null_ )
+insert ( 3494 to_regproc 11 10 12 1 0 0 0 f f f t f s s 1 0 24 25 _null_ _null_ _null_ _null_ _null_ to_regproc _null_ _null_ _null_ )
+insert ( 3479 to_regprocedure 11 10 12 1 0 0 0 f f f t f s s 1 0 2202 25 _null_ _null_ _null_ _null_ _null_ to_regprocedure _null_ _null_ _null_ )
+insert ( 46 textin 11 10 12 1 0 0 0 f f f t f i s 1 0 25 2275 _null_ _null_ _null_ _null_ _null_ textin _null_ _null_ _null_ )
+insert ( 47 textout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 25 _null_ _null_ _null_ _null_ _null_ textout _null_ _null_ _null_ )
+insert ( 48 tidin 11 10 12 1 0 0 0 f f f t f i s 1 0 27 2275 _null_ _null_ _null_ _null_ _null_ tidin _null_ _null_ _null_ )
+insert ( 49 tidout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 27 _null_ _null_ _null_ _null_ _null_ tidout _null_ _null_ _null_ )
+insert ( 50 xidin 11 10 12 1 0 0 0 f f f t f i s 1 0 28 2275 _null_ _null_ _null_ _null_ _null_ xidin _null_ _null_ _null_ )
+insert ( 51 xidout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 28 _null_ _null_ _null_ _null_ _null_ xidout _null_ _null_ _null_ )
+insert ( 5070 xid8in 11 10 12 1 0 0 0 f f f t f i s 1 0 5069 2275 _null_ _null_ _null_ _null_ _null_ xid8in _null_ _null_ _null_ )
+insert ( 5081 xid8out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 5069 _null_ _null_ _null_ _null_ _null_ xid8out _null_ _null_ _null_ )
+insert ( 5082 xid8recv 11 10 12 1 0 0 0 f f f t f i s 1 0 5069 2281 _null_ _null_ _null_ _null_ _null_ xid8recv _null_ _null_ _null_ )
+insert ( 5083 xid8send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 5069 _null_ _null_ _null_ _null_ _null_ xid8send _null_ _null_ _null_ )
+insert ( 52 cidin 11 10 12 1 0 0 0 f f f t f i s 1 0 29 2275 _null_ _null_ _null_ _null_ _null_ cidin _null_ _null_ _null_ )
+insert ( 53 cidout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 29 _null_ _null_ _null_ _null_ _null_ cidout _null_ _null_ _null_ )
+insert ( 54 oidvectorin 11 10 12 1 0 0 0 f f f t f i s 1 0 30 2275 _null_ _null_ _null_ _null_ _null_ oidvectorin _null_ _null_ _null_ )
+insert ( 55 oidvectorout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 30 _null_ _null_ _null_ _null_ _null_ oidvectorout _null_ _null_ _null_ )
+insert ( 56 boollt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "16 16" _null_ _null_ _null_ _null_ _null_ boollt _null_ _null_ _null_ )
+insert ( 57 boolgt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "16 16" _null_ _null_ _null_ _null_ _null_ boolgt _null_ _null_ _null_ )
+insert ( 60 booleq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "16 16" _null_ _null_ _null_ _null_ _null_ booleq _null_ _null_ _null_ )
+insert ( 61 chareq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "18 18" _null_ _null_ _null_ _null_ _null_ chareq _null_ _null_ _null_ )
+insert ( 62 nameeq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 19" _null_ _null_ _null_ _null_ _null_ nameeq _null_ _null_ _null_ )
+insert ( 63 int2eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 21" _null_ _null_ _null_ _null_ _null_ int2eq _null_ _null_ _null_ )
+insert ( 64 int2lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 21" _null_ _null_ _null_ _null_ _null_ int2lt _null_ _null_ _null_ )
+insert ( 65 int4eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ int4eq _null_ _null_ _null_ )
+insert ( 66 int4lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ int4lt _null_ _null_ _null_ )
+insert ( 67 texteq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ texteq _null_ _null_ _null_ )
+insert ( 3696 starts_with 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ text_starts_with _null_ _null_ _null_ )
+insert ( 68 xideq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "28 28" _null_ _null_ _null_ _null_ _null_ xideq _null_ _null_ _null_ )
+insert ( 3308 xidneq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "28 28" _null_ _null_ _null_ _null_ _null_ xidneq _null_ _null_ _null_ )
+insert ( 5084 xid8eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "5069 5069" _null_ _null_ _null_ _null_ _null_ xid8eq _null_ _null_ _null_ )
+insert ( 5085 xid8ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "5069 5069" _null_ _null_ _null_ _null_ _null_ xid8ne _null_ _null_ _null_ )
+insert ( 5034 xid8lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "5069 5069" _null_ _null_ _null_ _null_ _null_ xid8lt _null_ _null_ _null_ )
+insert ( 5035 xid8gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "5069 5069" _null_ _null_ _null_ _null_ _null_ xid8gt _null_ _null_ _null_ )
+insert ( 5036 xid8le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "5069 5069" _null_ _null_ _null_ _null_ _null_ xid8le _null_ _null_ _null_ )
+insert ( 5037 xid8ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "5069 5069" _null_ _null_ _null_ _null_ _null_ xid8ge _null_ _null_ _null_ )
+insert ( 5096 xid8cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "5069 5069" _null_ _null_ _null_ _null_ _null_ xid8cmp _null_ _null_ _null_ )
+insert ( 5071 xid 11 10 12 1 0 0 0 f f f t f i s 1 0 28 5069 _null_ _null_ _null_ _null_ _null_ xid8toxid _null_ _null_ _null_ )
+insert ( 69 cideq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "29 29" _null_ _null_ _null_ _null_ _null_ cideq _null_ _null_ _null_ )
+insert ( 70 charne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "18 18" _null_ _null_ _null_ _null_ _null_ charne _null_ _null_ _null_ )
+insert ( 1246 charlt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "18 18" _null_ _null_ _null_ _null_ _null_ charlt _null_ _null_ _null_ )
+insert ( 72 charle 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "18 18" _null_ _null_ _null_ _null_ _null_ charle _null_ _null_ _null_ )
+insert ( 73 chargt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "18 18" _null_ _null_ _null_ _null_ _null_ chargt _null_ _null_ _null_ )
+insert ( 74 charge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "18 18" _null_ _null_ _null_ _null_ _null_ charge _null_ _null_ _null_ )
+insert ( 77 int4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 18 _null_ _null_ _null_ _null_ _null_ chartoi4 _null_ _null_ _null_ )
+insert ( 78 char 11 10 12 1 0 0 0 f f f t f i s 1 0 18 23 _null_ _null_ _null_ _null_ _null_ i4tochar _null_ _null_ _null_ )
+insert ( 79 nameregexeq 11 10 12 1 0 0 1364 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ nameregexeq _null_ _null_ _null_ )
+insert ( 1252 nameregexne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ nameregexne _null_ _null_ _null_ )
+insert ( 1254 textregexeq 11 10 12 1 0 0 1364 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ textregexeq _null_ _null_ _null_ )
+insert ( 1256 textregexne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ textregexne _null_ _null_ _null_ )
+insert ( 1364 textregexeq_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ textregexeq_support _null_ _null_ _null_ )
+insert ( 1257 textlen 11 10 12 1 0 0 0 f f f t f i s 1 0 23 25 _null_ _null_ _null_ _null_ _null_ textlen _null_ _null_ _null_ )
+insert ( 1258 textcat 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ textcat _null_ _null_ _null_ )
+insert ( 84 boolne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "16 16" _null_ _null_ _null_ _null_ _null_ boolne _null_ _null_ _null_ )
+insert ( 89 version 11 10 12 1 0 0 0 f f f t f s s 0 0 25 "" _null_ _null_ _null_ _null_ _null_ pgsql_version _null_ _null_ _null_ )
+insert ( 86 pg_ddl_command_in 11 10 12 1 0 0 0 f f f t f i s 1 0 32 2275 _null_ _null_ _null_ _null_ _null_ pg_ddl_command_in _null_ _null_ _null_ )
+insert ( 87 pg_ddl_command_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 32 _null_ _null_ _null_ _null_ _null_ pg_ddl_command_out _null_ _null_ _null_ )
+insert ( 88 pg_ddl_command_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 32 2281 _null_ _null_ _null_ _null_ _null_ pg_ddl_command_recv _null_ _null_ _null_ )
+insert ( 90 pg_ddl_command_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 32 _null_ _null_ _null_ _null_ _null_ pg_ddl_command_send _null_ _null_ _null_ )
+insert ( 101 eqsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ eqsel _null_ _null_ _null_ )
+insert ( 102 neqsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ neqsel _null_ _null_ _null_ )
+insert ( 103 scalarltsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ scalarltsel _null_ _null_ _null_ )
+insert ( 104 scalargtsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ scalargtsel _null_ _null_ _null_ )
+insert ( 105 eqjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ eqjoinsel _null_ _null_ _null_ )
+insert ( 106 neqjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ neqjoinsel _null_ _null_ _null_ )
+insert ( 107 scalarltjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ scalarltjoinsel _null_ _null_ _null_ )
+insert ( 108 scalargtjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ scalargtjoinsel _null_ _null_ _null_ )
+insert ( 336 scalarlesel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ scalarlesel _null_ _null_ _null_ )
+insert ( 337 scalargesel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ scalargesel _null_ _null_ _null_ )
+insert ( 386 scalarlejoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ scalarlejoinsel _null_ _null_ _null_ )
+insert ( 398 scalargejoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ scalargejoinsel _null_ _null_ _null_ )
+insert ( 109 unknownin 11 10 12 1 0 0 0 f f f t f i s 1 0 705 2275 _null_ _null_ _null_ _null_ _null_ unknownin _null_ _null_ _null_ )
+insert ( 110 unknownout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 705 _null_ _null_ _null_ _null_ _null_ unknownout _null_ _null_ _null_ )
+insert ( 111 numeric_fac 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ numeric_fac _null_ _null_ _null_ )
+insert ( 115 box_above_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_above_eq _null_ _null_ _null_ )
+insert ( 116 box_below_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_below_eq _null_ _null_ _null_ )
+insert ( 117 point_in 11 10 12 1 0 0 0 f f f t f i s 1 0 600 2275 _null_ _null_ _null_ _null_ _null_ point_in _null_ _null_ _null_ )
+insert ( 118 point_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 600 _null_ _null_ _null_ _null_ _null_ point_out _null_ _null_ _null_ )
+insert ( 119 lseg_in 11 10 12 1 0 0 0 f f f t f i s 1 0 601 2275 _null_ _null_ _null_ _null_ _null_ lseg_in _null_ _null_ _null_ )
+insert ( 120 lseg_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 601 _null_ _null_ _null_ _null_ _null_ lseg_out _null_ _null_ _null_ )
+insert ( 121 path_in 11 10 12 1 0 0 0 f f f t f i s 1 0 602 2275 _null_ _null_ _null_ _null_ _null_ path_in _null_ _null_ _null_ )
+insert ( 122 path_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 602 _null_ _null_ _null_ _null_ _null_ path_out _null_ _null_ _null_ )
+insert ( 123 box_in 11 10 12 1 0 0 0 f f f t f i s 1 0 603 2275 _null_ _null_ _null_ _null_ _null_ box_in _null_ _null_ _null_ )
+insert ( 124 box_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 603 _null_ _null_ _null_ _null_ _null_ box_out _null_ _null_ _null_ )
+insert ( 125 box_overlap 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_overlap _null_ _null_ _null_ )
+insert ( 126 box_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_ge _null_ _null_ _null_ )
+insert ( 127 box_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_gt _null_ _null_ _null_ )
+insert ( 128 box_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_eq _null_ _null_ _null_ )
+insert ( 129 box_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_lt _null_ _null_ _null_ )
+insert ( 130 box_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_le _null_ _null_ _null_ )
+insert ( 131 point_above 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_above _null_ _null_ _null_ )
+insert ( 132 point_left 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_left _null_ _null_ _null_ )
+insert ( 133 point_right 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_right _null_ _null_ _null_ )
+insert ( 134 point_below 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_below _null_ _null_ _null_ )
+insert ( 135 point_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_eq _null_ _null_ _null_ )
+insert ( 136 on_pb 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 603" _null_ _null_ _null_ _null_ _null_ on_pb _null_ _null_ _null_ )
+insert ( 137 on_ppath 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 602" _null_ _null_ _null_ _null_ _null_ on_ppath _null_ _null_ _null_ )
+insert ( 138 box_center 11 10 12 1 0 0 0 f f f t f i s 1 0 600 603 _null_ _null_ _null_ _null_ _null_ box_center _null_ _null_ _null_ )
+insert ( 139 areasel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ areasel _null_ _null_ _null_ )
+insert ( 140 areajoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ areajoinsel _null_ _null_ _null_ )
+insert ( 141 int4mul 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4mul _null_ _null_ _null_ )
+insert ( 144 int4ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ int4ne _null_ _null_ _null_ )
+insert ( 145 int2ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 21" _null_ _null_ _null_ _null_ _null_ int2ne _null_ _null_ _null_ )
+insert ( 146 int2gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 21" _null_ _null_ _null_ _null_ _null_ int2gt _null_ _null_ _null_ )
+insert ( 147 int4gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ int4gt _null_ _null_ _null_ )
+insert ( 148 int2le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 21" _null_ _null_ _null_ _null_ _null_ int2le _null_ _null_ _null_ )
+insert ( 149 int4le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ int4le _null_ _null_ _null_ )
+insert ( 150 int4ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ int4ge _null_ _null_ _null_ )
+insert ( 151 int2ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 21" _null_ _null_ _null_ _null_ _null_ int2ge _null_ _null_ _null_ )
+insert ( 152 int2mul 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2mul _null_ _null_ _null_ )
+insert ( 153 int2div 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2div _null_ _null_ _null_ )
+insert ( 154 int4div 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4div _null_ _null_ _null_ )
+insert ( 155 int2mod 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2mod _null_ _null_ _null_ )
+insert ( 156 int4mod 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4mod _null_ _null_ _null_ )
+insert ( 157 textne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ textne _null_ _null_ _null_ )
+insert ( 158 int24eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 23" _null_ _null_ _null_ _null_ _null_ int24eq _null_ _null_ _null_ )
+insert ( 159 int42eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 21" _null_ _null_ _null_ _null_ _null_ int42eq _null_ _null_ _null_ )
+insert ( 160 int24lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 23" _null_ _null_ _null_ _null_ _null_ int24lt _null_ _null_ _null_ )
+insert ( 161 int42lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 21" _null_ _null_ _null_ _null_ _null_ int42lt _null_ _null_ _null_ )
+insert ( 162 int24gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 23" _null_ _null_ _null_ _null_ _null_ int24gt _null_ _null_ _null_ )
+insert ( 163 int42gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 21" _null_ _null_ _null_ _null_ _null_ int42gt _null_ _null_ _null_ )
+insert ( 164 int24ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 23" _null_ _null_ _null_ _null_ _null_ int24ne _null_ _null_ _null_ )
+insert ( 165 int42ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 21" _null_ _null_ _null_ _null_ _null_ int42ne _null_ _null_ _null_ )
+insert ( 166 int24le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 23" _null_ _null_ _null_ _null_ _null_ int24le _null_ _null_ _null_ )
+insert ( 167 int42le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 21" _null_ _null_ _null_ _null_ _null_ int42le _null_ _null_ _null_ )
+insert ( 168 int24ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 23" _null_ _null_ _null_ _null_ _null_ int24ge _null_ _null_ _null_ )
+insert ( 169 int42ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 21" _null_ _null_ _null_ _null_ _null_ int42ge _null_ _null_ _null_ )
+insert ( 170 int24mul 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "21 23" _null_ _null_ _null_ _null_ _null_ int24mul _null_ _null_ _null_ )
+insert ( 171 int42mul 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 21" _null_ _null_ _null_ _null_ _null_ int42mul _null_ _null_ _null_ )
+insert ( 172 int24div 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "21 23" _null_ _null_ _null_ _null_ _null_ int24div _null_ _null_ _null_ )
+insert ( 173 int42div 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 21" _null_ _null_ _null_ _null_ _null_ int42div _null_ _null_ _null_ )
+insert ( 176 int2pl 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2pl _null_ _null_ _null_ )
+insert ( 177 int4pl 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4pl _null_ _null_ _null_ )
+insert ( 178 int24pl 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "21 23" _null_ _null_ _null_ _null_ _null_ int24pl _null_ _null_ _null_ )
+insert ( 179 int42pl 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 21" _null_ _null_ _null_ _null_ _null_ int42pl _null_ _null_ _null_ )
+insert ( 180 int2mi 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2mi _null_ _null_ _null_ )
+insert ( 181 int4mi 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4mi _null_ _null_ _null_ )
+insert ( 182 int24mi 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "21 23" _null_ _null_ _null_ _null_ _null_ int24mi _null_ _null_ _null_ )
+insert ( 183 int42mi 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 21" _null_ _null_ _null_ _null_ _null_ int42mi _null_ _null_ _null_ )
+insert ( 184 oideq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oideq _null_ _null_ _null_ )
+insert ( 185 oidne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oidne _null_ _null_ _null_ )
+insert ( 186 box_same 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_same _null_ _null_ _null_ )
+insert ( 187 box_contain 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_contain _null_ _null_ _null_ )
+insert ( 188 box_left 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_left _null_ _null_ _null_ )
+insert ( 189 box_overleft 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_overleft _null_ _null_ _null_ )
+insert ( 190 box_overright 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_overright _null_ _null_ _null_ )
+insert ( 191 box_right 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_right _null_ _null_ _null_ )
+insert ( 192 box_contained 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_contained _null_ _null_ _null_ )
+insert ( 193 box_contain_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_contain_pt _null_ _null_ _null_ )
+insert ( 195 pg_node_tree_in 11 10 12 1 0 0 0 f f f t f i s 1 0 194 2275 _null_ _null_ _null_ _null_ _null_ pg_node_tree_in _null_ _null_ _null_ )
+insert ( 196 pg_node_tree_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 194 _null_ _null_ _null_ _null_ _null_ pg_node_tree_out _null_ _null_ _null_ )
+insert ( 197 pg_node_tree_recv 11 10 12 1 0 0 0 f f f t f s s 1 0 194 2281 _null_ _null_ _null_ _null_ _null_ pg_node_tree_recv _null_ _null_ _null_ )
+insert ( 198 pg_node_tree_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 194 _null_ _null_ _null_ _null_ _null_ pg_node_tree_send _null_ _null_ _null_ )
+insert ( 200 float4in 11 10 12 1 0 0 0 f f f t f i s 1 0 700 2275 _null_ _null_ _null_ _null_ _null_ float4in _null_ _null_ _null_ )
+insert ( 201 float4out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 700 _null_ _null_ _null_ _null_ _null_ float4out _null_ _null_ _null_ )
+insert ( 202 float4mul 11 10 12 1 0 0 0 f f f t f i s 2 0 700 "700 700" _null_ _null_ _null_ _null_ _null_ float4mul _null_ _null_ _null_ )
+insert ( 203 float4div 11 10 12 1 0 0 0 f f f t f i s 2 0 700 "700 700" _null_ _null_ _null_ _null_ _null_ float4div _null_ _null_ _null_ )
+insert ( 204 float4pl 11 10 12 1 0 0 0 f f f t f i s 2 0 700 "700 700" _null_ _null_ _null_ _null_ _null_ float4pl _null_ _null_ _null_ )
+insert ( 205 float4mi 11 10 12 1 0 0 0 f f f t f i s 2 0 700 "700 700" _null_ _null_ _null_ _null_ _null_ float4mi _null_ _null_ _null_ )
+insert ( 206 float4um 11 10 12 1 0 0 0 f f f t f i s 1 0 700 700 _null_ _null_ _null_ _null_ _null_ float4um _null_ _null_ _null_ )
+insert ( 207 float4abs 11 10 12 1 0 0 0 f f f t f i s 1 0 700 700 _null_ _null_ _null_ _null_ _null_ float4abs _null_ _null_ _null_ )
+insert ( 208 float4_accum 11 10 12 1 0 0 0 f f f t f i s 2 0 1022 "1022 700" _null_ _null_ _null_ _null_ _null_ float4_accum _null_ _null_ _null_ )
+insert ( 209 float4larger 11 10 12 1 0 0 0 f f f t f i s 2 0 700 "700 700" _null_ _null_ _null_ _null_ _null_ float4larger _null_ _null_ _null_ )
+insert ( 211 float4smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 700 "700 700" _null_ _null_ _null_ _null_ _null_ float4smaller _null_ _null_ _null_ )
+insert ( 212 int4um 11 10 12 1 0 0 0 f f f t f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ int4um _null_ _null_ _null_ )
+insert ( 213 int2um 11 10 12 1 0 0 0 f f f t f i s 1 0 21 21 _null_ _null_ _null_ _null_ _null_ int2um _null_ _null_ _null_ )
+insert ( 214 float8in 11 10 12 1 0 0 0 f f f t f i s 1 0 701 2275 _null_ _null_ _null_ _null_ _null_ float8in _null_ _null_ _null_ )
+insert ( 215 float8out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 701 _null_ _null_ _null_ _null_ _null_ float8out _null_ _null_ _null_ )
+insert ( 216 float8mul 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ float8mul _null_ _null_ _null_ )
+insert ( 217 float8div 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ float8div _null_ _null_ _null_ )
+insert ( 218 float8pl 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ float8pl _null_ _null_ _null_ )
+insert ( 219 float8mi 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ float8mi _null_ _null_ _null_ )
+insert ( 220 float8um 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ float8um _null_ _null_ _null_ )
+insert ( 221 float8abs 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ float8abs _null_ _null_ _null_ )
+insert ( 222 float8_accum 11 10 12 1 0 0 0 f f f t f i s 2 0 1022 "1022 701" _null_ _null_ _null_ _null_ _null_ float8_accum _null_ _null_ _null_ )
+insert ( 276 float8_combine 11 10 12 1 0 0 0 f f f t f i s 2 0 1022 "1022 1022" _null_ _null_ _null_ _null_ _null_ float8_combine _null_ _null_ _null_ )
+insert ( 223 float8larger 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ float8larger _null_ _null_ _null_ )
+insert ( 224 float8smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ float8smaller _null_ _null_ _null_ )
+insert ( 225 lseg_center 11 10 12 1 0 0 0 f f f t f i s 1 0 600 601 _null_ _null_ _null_ _null_ _null_ lseg_center _null_ _null_ _null_ )
+insert ( 226 path_center 11 10 12 1 0 0 0 f f f t f i s 1 0 600 602 _null_ _null_ _null_ _null_ _null_ path_center _null_ _null_ _null_ )
+insert ( 227 poly_center 11 10 12 1 0 0 0 f f f t f i s 1 0 600 604 _null_ _null_ _null_ _null_ _null_ poly_center _null_ _null_ _null_ )
+insert ( 228 dround 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dround _null_ _null_ _null_ )
+insert ( 229 dtrunc 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dtrunc _null_ _null_ _null_ )
+insert ( 2308 ceil 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dceil _null_ _null_ _null_ )
+insert ( 2320 ceiling 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dceil _null_ _null_ _null_ )
+insert ( 2309 floor 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dfloor _null_ _null_ _null_ )
+insert ( 2310 sign 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dsign _null_ _null_ _null_ )
+insert ( 230 dsqrt 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dsqrt _null_ _null_ _null_ )
+insert ( 231 dcbrt 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dcbrt _null_ _null_ _null_ )
+insert ( 232 dpow 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ dpow _null_ _null_ _null_ )
+insert ( 233 dexp 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dexp _null_ _null_ _null_ )
+insert ( 234 dlog1 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dlog1 _null_ _null_ _null_ )
+insert ( 235 float8 11 10 12 1 0 0 0 f f f t f i s 1 0 701 21 _null_ _null_ _null_ _null_ _null_ i2tod _null_ _null_ _null_ )
+insert ( 236 float4 11 10 12 1 0 0 0 f f f t f i s 1 0 700 21 _null_ _null_ _null_ _null_ _null_ i2tof _null_ _null_ _null_ )
+insert ( 237 int2 11 10 12 1 0 0 0 f f f t f i s 1 0 21 701 _null_ _null_ _null_ _null_ _null_ dtoi2 _null_ _null_ _null_ )
+insert ( 238 int2 11 10 12 1 0 0 0 f f f t f i s 1 0 21 700 _null_ _null_ _null_ _null_ _null_ ftoi2 _null_ _null_ _null_ )
+insert ( 239 line_distance 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "628 628" _null_ _null_ _null_ _null_ _null_ line_distance _null_ _null_ _null_ )
+insert ( 240 nameeqtext 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ nameeqtext _null_ _null_ _null_ )
+insert ( 241 namelttext 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ namelttext _null_ _null_ _null_ )
+insert ( 242 nameletext 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ nameletext _null_ _null_ _null_ )
+insert ( 243 namegetext 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ namegetext _null_ _null_ _null_ )
+insert ( 244 namegttext 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ namegttext _null_ _null_ _null_ )
+insert ( 245 namenetext 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ namenetext _null_ _null_ _null_ )
+insert ( 246 btnametextcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "19 25" _null_ _null_ _null_ _null_ _null_ btnametextcmp _null_ _null_ _null_ )
+insert ( 247 texteqname 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 19" _null_ _null_ _null_ _null_ _null_ texteqname _null_ _null_ _null_ )
+insert ( 248 textltname 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 19" _null_ _null_ _null_ _null_ _null_ textltname _null_ _null_ _null_ )
+insert ( 249 textlename 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 19" _null_ _null_ _null_ _null_ _null_ textlename _null_ _null_ _null_ )
+insert ( 250 textgename 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 19" _null_ _null_ _null_ _null_ _null_ textgename _null_ _null_ _null_ )
+insert ( 251 textgtname 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 19" _null_ _null_ _null_ _null_ _null_ textgtname _null_ _null_ _null_ )
+insert ( 252 textnename 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 19" _null_ _null_ _null_ _null_ _null_ textnename _null_ _null_ _null_ )
+insert ( 253 bttextnamecmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "25 19" _null_ _null_ _null_ _null_ _null_ bttextnamecmp _null_ _null_ _null_ )
+insert ( 266 nameconcatoid 11 10 12 1 0 0 0 f f f t f i s 2 0 19 "19 26" _null_ _null_ _null_ _null_ _null_ nameconcatoid _null_ _null_ _null_ )
+insert ( 274 timeofday 11 10 12 1 0 0 0 f f f t f v s 0 0 25 "" _null_ _null_ _null_ _null_ _null_ timeofday _null_ _null_ _null_ )
+insert ( 277 inter_sl 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "601 628" _null_ _null_ _null_ _null_ _null_ inter_sl _null_ _null_ _null_ )
+insert ( 278 inter_lb 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "628 603" _null_ _null_ _null_ _null_ _null_ inter_lb _null_ _null_ _null_ )
+insert ( 279 float48mul 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "700 701" _null_ _null_ _null_ _null_ _null_ float48mul _null_ _null_ _null_ )
+insert ( 280 float48div 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "700 701" _null_ _null_ _null_ _null_ _null_ float48div _null_ _null_ _null_ )
+insert ( 281 float48pl 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "700 701" _null_ _null_ _null_ _null_ _null_ float48pl _null_ _null_ _null_ )
+insert ( 282 float48mi 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "700 701" _null_ _null_ _null_ _null_ _null_ float48mi _null_ _null_ _null_ )
+insert ( 283 float84mul 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 700" _null_ _null_ _null_ _null_ _null_ float84mul _null_ _null_ _null_ )
+insert ( 284 float84div 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 700" _null_ _null_ _null_ _null_ _null_ float84div _null_ _null_ _null_ )
+insert ( 285 float84pl 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 700" _null_ _null_ _null_ _null_ _null_ float84pl _null_ _null_ _null_ )
+insert ( 286 float84mi 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 700" _null_ _null_ _null_ _null_ _null_ float84mi _null_ _null_ _null_ )
+insert ( 287 float4eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 700" _null_ _null_ _null_ _null_ _null_ float4eq _null_ _null_ _null_ )
+insert ( 288 float4ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 700" _null_ _null_ _null_ _null_ _null_ float4ne _null_ _null_ _null_ )
+insert ( 289 float4lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 700" _null_ _null_ _null_ _null_ _null_ float4lt _null_ _null_ _null_ )
+insert ( 290 float4le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 700" _null_ _null_ _null_ _null_ _null_ float4le _null_ _null_ _null_ )
+insert ( 291 float4gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 700" _null_ _null_ _null_ _null_ _null_ float4gt _null_ _null_ _null_ )
+insert ( 292 float4ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 700" _null_ _null_ _null_ _null_ _null_ float4ge _null_ _null_ _null_ )
+insert ( 293 float8eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 701" _null_ _null_ _null_ _null_ _null_ float8eq _null_ _null_ _null_ )
+insert ( 294 float8ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 701" _null_ _null_ _null_ _null_ _null_ float8ne _null_ _null_ _null_ )
+insert ( 295 float8lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 701" _null_ _null_ _null_ _null_ _null_ float8lt _null_ _null_ _null_ )
+insert ( 296 float8le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 701" _null_ _null_ _null_ _null_ _null_ float8le _null_ _null_ _null_ )
+insert ( 297 float8gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 701" _null_ _null_ _null_ _null_ _null_ float8gt _null_ _null_ _null_ )
+insert ( 298 float8ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 701" _null_ _null_ _null_ _null_ _null_ float8ge _null_ _null_ _null_ )
+insert ( 299 float48eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 701" _null_ _null_ _null_ _null_ _null_ float48eq _null_ _null_ _null_ )
+insert ( 300 float48ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 701" _null_ _null_ _null_ _null_ _null_ float48ne _null_ _null_ _null_ )
+insert ( 301 float48lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 701" _null_ _null_ _null_ _null_ _null_ float48lt _null_ _null_ _null_ )
+insert ( 302 float48le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 701" _null_ _null_ _null_ _null_ _null_ float48le _null_ _null_ _null_ )
+insert ( 303 float48gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 701" _null_ _null_ _null_ _null_ _null_ float48gt _null_ _null_ _null_ )
+insert ( 304 float48ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "700 701" _null_ _null_ _null_ _null_ _null_ float48ge _null_ _null_ _null_ )
+insert ( 305 float84eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 700" _null_ _null_ _null_ _null_ _null_ float84eq _null_ _null_ _null_ )
+insert ( 306 float84ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 700" _null_ _null_ _null_ _null_ _null_ float84ne _null_ _null_ _null_ )
+insert ( 307 float84lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 700" _null_ _null_ _null_ _null_ _null_ float84lt _null_ _null_ _null_ )
+insert ( 308 float84le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 700" _null_ _null_ _null_ _null_ _null_ float84le _null_ _null_ _null_ )
+insert ( 309 float84gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 700" _null_ _null_ _null_ _null_ _null_ float84gt _null_ _null_ _null_ )
+insert ( 310 float84ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "701 700" _null_ _null_ _null_ _null_ _null_ float84ge _null_ _null_ _null_ )
+insert ( 320 width_bucket 11 10 12 1 0 0 0 f f f t f i s 4 0 23 "701 701 701 23" _null_ _null_ _null_ _null_ _null_ width_bucket_float8 _null_ _null_ _null_ )
+insert ( 311 float8 11 10 12 1 0 0 0 f f f t f i s 1 0 701 700 _null_ _null_ _null_ _null_ _null_ ftod _null_ _null_ _null_ )
+insert ( 312 float4 11 10 12 1 0 0 0 f f f t f i s 1 0 700 701 _null_ _null_ _null_ _null_ _null_ dtof _null_ _null_ _null_ )
+insert ( 313 int4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 21 _null_ _null_ _null_ _null_ _null_ i2toi4 _null_ _null_ _null_ )
+insert ( 314 int2 11 10 12 1 0 0 0 f f f t f i s 1 0 21 23 _null_ _null_ _null_ _null_ _null_ i4toi2 _null_ _null_ _null_ )
+insert ( 316 float8 11 10 12 1 0 0 0 f f f t f i s 1 0 701 23 _null_ _null_ _null_ _null_ _null_ i4tod _null_ _null_ _null_ )
+insert ( 317 int4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 701 _null_ _null_ _null_ _null_ _null_ dtoi4 _null_ _null_ _null_ )
+insert ( 318 float4 11 10 12 1 0 0 0 f f f t f i s 1 0 700 23 _null_ _null_ _null_ _null_ _null_ i4tof _null_ _null_ _null_ )
+insert ( 319 int4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 700 _null_ _null_ _null_ _null_ _null_ ftoi4 _null_ _null_ _null_ )
+insert ( 3 heap_tableam_handler 11 10 12 1 0 0 0 f f f t f v s 1 0 269 2281 _null_ _null_ _null_ _null_ _null_ heap_tableam_handler _null_ _null_ _null_ )
+insert ( 330 bthandler 11 10 12 1 0 0 0 f f f t f v s 1 0 325 2281 _null_ _null_ _null_ _null_ _null_ bthandler _null_ _null_ _null_ )
+insert ( 331 hashhandler 11 10 12 1 0 0 0 f f f t f v s 1 0 325 2281 _null_ _null_ _null_ _null_ _null_ hashhandler _null_ _null_ _null_ )
+insert ( 332 gisthandler 11 10 12 1 0 0 0 f f f t f v s 1 0 325 2281 _null_ _null_ _null_ _null_ _null_ gisthandler _null_ _null_ _null_ )
+insert ( 333 ginhandler 11 10 12 1 0 0 0 f f f t f v s 1 0 325 2281 _null_ _null_ _null_ _null_ _null_ ginhandler _null_ _null_ _null_ )
+insert ( 334 spghandler 11 10 12 1 0 0 0 f f f t f v s 1 0 325 2281 _null_ _null_ _null_ _null_ _null_ spghandler _null_ _null_ _null_ )
+insert ( 335 brinhandler 11 10 12 1 0 0 0 f f f t f v s 1 0 325 2281 _null_ _null_ _null_ _null_ _null_ brinhandler _null_ _null_ _null_ )
+insert ( 3952 brin_summarize_new_values 11 10 12 1 0 0 0 f f f t f v u 1 0 23 2205 _null_ _null_ _null_ _null_ _null_ brin_summarize_new_values _null_ _null_ _null_ )
+insert ( 3999 brin_summarize_range 11 10 12 1 0 0 0 f f f t f v u 2 0 23 "2205 20" _null_ _null_ _null_ _null_ _null_ brin_summarize_range _null_ _null_ _null_ )
+insert ( 4014 brin_desummarize_range 11 10 12 1 0 0 0 f f f t f v u 2 0 2278 "2205 20" _null_ _null_ _null_ _null_ _null_ brin_desummarize_range _null_ _null_ _null_ )
+insert ( 338 amvalidate 11 10 12 1 0 0 0 f f f t f v s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ amvalidate _null_ _null_ _null_ )
+insert ( 636 pg_indexam_has_property 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ pg_indexam_has_property _null_ _null_ _null_ )
+insert ( 637 pg_index_has_property 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "2205 25" _null_ _null_ _null_ _null_ _null_ pg_index_has_property _null_ _null_ _null_ )
+insert ( 638 pg_index_column_has_property 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "2205 23 25" _null_ _null_ _null_ _null_ _null_ pg_index_column_has_property _null_ _null_ _null_ )
+insert ( 676 pg_indexam_progress_phasename 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "26 20" _null_ _null_ _null_ _null_ _null_ pg_indexam_progress_phasename _null_ _null_ _null_ )
+insert ( 339 poly_same 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_same _null_ _null_ _null_ )
+insert ( 340 poly_contain 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_contain _null_ _null_ _null_ )
+insert ( 341 poly_left 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_left _null_ _null_ _null_ )
+insert ( 342 poly_overleft 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_overleft _null_ _null_ _null_ )
+insert ( 343 poly_overright 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_overright _null_ _null_ _null_ )
+insert ( 344 poly_right 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_right _null_ _null_ _null_ )
+insert ( 345 poly_contained 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_contained _null_ _null_ _null_ )
+insert ( 346 poly_overlap 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_overlap _null_ _null_ _null_ )
+insert ( 347 poly_in 11 10 12 1 0 0 0 f f f t f i s 1 0 604 2275 _null_ _null_ _null_ _null_ _null_ poly_in _null_ _null_ _null_ )
+insert ( 348 poly_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 604 _null_ _null_ _null_ _null_ _null_ poly_out _null_ _null_ _null_ )
+insert ( 350 btint2cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "21 21" _null_ _null_ _null_ _null_ _null_ btint2cmp _null_ _null_ _null_ )
+insert ( 3129 btint2sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ btint2sortsupport _null_ _null_ _null_ )
+insert ( 351 btint4cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ btint4cmp _null_ _null_ _null_ )
+insert ( 3130 btint4sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ btint4sortsupport _null_ _null_ _null_ )
+insert ( 842 btint8cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "20 20" _null_ _null_ _null_ _null_ _null_ btint8cmp _null_ _null_ _null_ )
+insert ( 3131 btint8sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ btint8sortsupport _null_ _null_ _null_ )
+insert ( 354 btfloat4cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "700 700" _null_ _null_ _null_ _null_ _null_ btfloat4cmp _null_ _null_ _null_ )
+insert ( 3132 btfloat4sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ btfloat4sortsupport _null_ _null_ _null_ )
+insert ( 355 btfloat8cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "701 701" _null_ _null_ _null_ _null_ _null_ btfloat8cmp _null_ _null_ _null_ )
+insert ( 3133 btfloat8sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ btfloat8sortsupport _null_ _null_ _null_ )
+insert ( 356 btoidcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "26 26" _null_ _null_ _null_ _null_ _null_ btoidcmp _null_ _null_ _null_ )
+insert ( 3134 btoidsortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ btoidsortsupport _null_ _null_ _null_ )
+insert ( 404 btoidvectorcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "30 30" _null_ _null_ _null_ _null_ _null_ btoidvectorcmp _null_ _null_ _null_ )
+insert ( 358 btcharcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "18 18" _null_ _null_ _null_ _null_ _null_ btcharcmp _null_ _null_ _null_ )
+insert ( 359 btnamecmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "19 19" _null_ _null_ _null_ _null_ _null_ btnamecmp _null_ _null_ _null_ )
+insert ( 3135 btnamesortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ btnamesortsupport _null_ _null_ _null_ )
+insert ( 360 bttextcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "25 25" _null_ _null_ _null_ _null_ _null_ bttextcmp _null_ _null_ _null_ )
+insert ( 3255 bttextsortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ bttextsortsupport _null_ _null_ _null_ )
+insert ( 5050 btvarstrequalimage 11 10 12 1 0 0 0 f f f t f i s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ btvarstrequalimage _null_ _null_ _null_ )
+insert ( 377 cash_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "790 790" _null_ _null_ _null_ _null_ _null_ cash_cmp _null_ _null_ _null_ )
+insert ( 382 btarraycmp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "2277 2277" _null_ _null_ _null_ _null_ _null_ btarraycmp _null_ _null_ _null_ )
+insert ( 4126 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "20 20 20 16 16" _null_ _null_ _null_ _null_ _null_ in_range_int8_int8 _null_ _null_ _null_ )
+insert ( 4127 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "23 23 20 16 16" _null_ _null_ _null_ _null_ _null_ in_range_int4_int8 _null_ _null_ _null_ )
+insert ( 4128 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "23 23 23 16 16" _null_ _null_ _null_ _null_ _null_ in_range_int4_int4 _null_ _null_ _null_ )
+insert ( 4129 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "23 23 21 16 16" _null_ _null_ _null_ _null_ _null_ in_range_int4_int2 _null_ _null_ _null_ )
+insert ( 4130 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "21 21 20 16 16" _null_ _null_ _null_ _null_ _null_ in_range_int2_int8 _null_ _null_ _null_ )
+insert ( 4131 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "21 21 23 16 16" _null_ _null_ _null_ _null_ _null_ in_range_int2_int4 _null_ _null_ _null_ )
+insert ( 4132 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "21 21 21 16 16" _null_ _null_ _null_ _null_ _null_ in_range_int2_int2 _null_ _null_ _null_ )
+insert ( 4139 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "701 701 701 16 16" _null_ _null_ _null_ _null_ _null_ in_range_float8_float8 _null_ _null_ _null_ )
+insert ( 4140 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "700 700 701 16 16" _null_ _null_ _null_ _null_ _null_ in_range_float4_float8 _null_ _null_ _null_ )
+insert ( 4141 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "1700 1700 1700 16 16" _null_ _null_ _null_ _null_ _null_ in_range_numeric_numeric _null_ _null_ _null_ )
+insert ( 361 lseg_distance 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_distance _null_ _null_ _null_ )
+insert ( 362 lseg_interpt 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_interpt _null_ _null_ _null_ )
+insert ( 363 dist_ps 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "600 601" _null_ _null_ _null_ _null_ _null_ dist_ps _null_ _null_ _null_ )
+insert ( 380 dist_sp 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "601 600" _null_ _null_ _null_ _null_ _null_ dist_sp _null_ _null_ _null_ )
+insert ( 364 dist_pb 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "600 603" _null_ _null_ _null_ _null_ _null_ dist_pb _null_ _null_ _null_ )
+insert ( 357 dist_bp 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "603 600" _null_ _null_ _null_ _null_ _null_ dist_bp _null_ _null_ _null_ )
+insert ( 365 dist_sb 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "601 603" _null_ _null_ _null_ _null_ _null_ dist_sb _null_ _null_ _null_ )
+insert ( 381 dist_bs 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "603 601" _null_ _null_ _null_ _null_ _null_ dist_bs _null_ _null_ _null_ )
+insert ( 366 close_ps 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "600 601" _null_ _null_ _null_ _null_ _null_ close_ps _null_ _null_ _null_ )
+insert ( 367 close_pb 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "600 603" _null_ _null_ _null_ _null_ _null_ close_pb _null_ _null_ _null_ )
+insert ( 368 close_sb 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "601 603" _null_ _null_ _null_ _null_ _null_ close_sb _null_ _null_ _null_ )
+insert ( 369 on_ps 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 601" _null_ _null_ _null_ _null_ _null_ on_ps _null_ _null_ _null_ )
+insert ( 370 path_distance 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "602 602" _null_ _null_ _null_ _null_ _null_ path_distance _null_ _null_ _null_ )
+insert ( 371 dist_ppath 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "600 602" _null_ _null_ _null_ _null_ _null_ dist_ppath _null_ _null_ _null_ )
+insert ( 421 dist_pathp 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "602 600" _null_ _null_ _null_ _null_ _null_ dist_pathp _null_ _null_ _null_ )
+insert ( 372 on_sb 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "601 603" _null_ _null_ _null_ _null_ _null_ on_sb _null_ _null_ _null_ )
+insert ( 373 inter_sb 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "601 603" _null_ _null_ _null_ _null_ _null_ inter_sb _null_ _null_ _null_ )
+insert ( 401 text 11 10 12 1 0 0 0 f f f t f i s 1 0 25 1042 _null_ _null_ _null_ _null_ _null_ rtrim1 _null_ _null_ _null_ )
+insert ( 406 text 11 10 12 1 0 0 0 f f f t f i s 1 0 25 19 _null_ _null_ _null_ _null_ _null_ name_text _null_ _null_ _null_ )
+insert ( 407 name 11 10 12 1 0 0 0 f f f t f i s 1 0 19 25 _null_ _null_ _null_ _null_ _null_ text_name _null_ _null_ _null_ )
+insert ( 408 bpchar 11 10 12 1 0 0 0 f f f t f i s 1 0 1042 19 _null_ _null_ _null_ _null_ _null_ name_bpchar _null_ _null_ _null_ )
+insert ( 409 name 11 10 12 1 0 0 0 f f f t f i s 1 0 19 1042 _null_ _null_ _null_ _null_ _null_ bpchar_name _null_ _null_ _null_ )
+insert ( 449 hashint2 11 10 12 1 0 0 0 f f f t f i s 1 0 23 21 _null_ _null_ _null_ _null_ _null_ hashint2 _null_ _null_ _null_ )
+insert ( 441 hashint2extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "21 20" _null_ _null_ _null_ _null_ _null_ hashint2extended _null_ _null_ _null_ )
+insert ( 450 hashint4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ hashint4 _null_ _null_ _null_ )
+insert ( 425 hashint4extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "23 20" _null_ _null_ _null_ _null_ _null_ hashint4extended _null_ _null_ _null_ )
+insert ( 949 hashint8 11 10 12 1 0 0 0 f f f t f i s 1 0 23 20 _null_ _null_ _null_ _null_ _null_ hashint8 _null_ _null_ _null_ )
+insert ( 442 hashint8extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ hashint8extended _null_ _null_ _null_ )
+insert ( 451 hashfloat4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 700 _null_ _null_ _null_ _null_ _null_ hashfloat4 _null_ _null_ _null_ )
+insert ( 443 hashfloat4extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "700 20" _null_ _null_ _null_ _null_ _null_ hashfloat4extended _null_ _null_ _null_ )
+insert ( 452 hashfloat8 11 10 12 1 0 0 0 f f f t f i s 1 0 23 701 _null_ _null_ _null_ _null_ _null_ hashfloat8 _null_ _null_ _null_ )
+insert ( 444 hashfloat8extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "701 20" _null_ _null_ _null_ _null_ _null_ hashfloat8extended _null_ _null_ _null_ )
+insert ( 453 hashoid 11 10 12 1 0 0 0 f f f t f i s 1 0 23 26 _null_ _null_ _null_ _null_ _null_ hashoid _null_ _null_ _null_ )
+insert ( 445 hashoidextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "26 20" _null_ _null_ _null_ _null_ _null_ hashoidextended _null_ _null_ _null_ )
+insert ( 454 hashchar 11 10 12 1 0 0 0 f f f t f i s 1 0 23 18 _null_ _null_ _null_ _null_ _null_ hashchar _null_ _null_ _null_ )
+insert ( 446 hashcharextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "18 20" _null_ _null_ _null_ _null_ _null_ hashcharextended _null_ _null_ _null_ )
+insert ( 455 hashname 11 10 12 1 0 0 0 f f f t f i s 1 0 23 19 _null_ _null_ _null_ _null_ _null_ hashname _null_ _null_ _null_ )
+insert ( 447 hashnameextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "19 20" _null_ _null_ _null_ _null_ _null_ hashnameextended _null_ _null_ _null_ )
+insert ( 400 hashtext 11 10 12 1 0 0 0 f f f t f i s 1 0 23 25 _null_ _null_ _null_ _null_ _null_ hashtext _null_ _null_ _null_ )
+insert ( 448 hashtextextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "25 20" _null_ _null_ _null_ _null_ _null_ hashtextextended _null_ _null_ _null_ )
+insert ( 456 hashvarlena 11 10 12 1 0 0 0 f f f t f i s 1 0 23 2281 _null_ _null_ _null_ _null_ _null_ hashvarlena _null_ _null_ _null_ )
+insert ( 772 hashvarlenaextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "2281 20" _null_ _null_ _null_ _null_ _null_ hashvarlenaextended _null_ _null_ _null_ )
+insert ( 457 hashoidvector 11 10 12 1 0 0 0 f f f t f i s 1 0 23 30 _null_ _null_ _null_ _null_ _null_ hashoidvector _null_ _null_ _null_ )
+insert ( 776 hashoidvectorextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "30 20" _null_ _null_ _null_ _null_ _null_ hashoidvectorextended _null_ _null_ _null_ )
+insert ( 329 hash_aclitem 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1033 _null_ _null_ _null_ _null_ _null_ hash_aclitem _null_ _null_ _null_ )
+insert ( 777 hash_aclitem_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "1033 20" _null_ _null_ _null_ _null_ _null_ hash_aclitem_extended _null_ _null_ _null_ )
+insert ( 399 hashmacaddr 11 10 12 1 0 0 0 f f f t f i s 1 0 23 829 _null_ _null_ _null_ _null_ _null_ hashmacaddr _null_ _null_ _null_ )
+insert ( 778 hashmacaddrextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "829 20" _null_ _null_ _null_ _null_ _null_ hashmacaddrextended _null_ _null_ _null_ )
+insert ( 422 hashinet 11 10 12 1 0 0 0 f f f t f i s 1 0 23 869 _null_ _null_ _null_ _null_ _null_ hashinet _null_ _null_ _null_ )
+insert ( 779 hashinetextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "869 20" _null_ _null_ _null_ _null_ _null_ hashinetextended _null_ _null_ _null_ )
+insert ( 432 hash_numeric 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1700 _null_ _null_ _null_ _null_ _null_ hash_numeric _null_ _null_ _null_ )
+insert ( 780 hash_numeric_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "1700 20" _null_ _null_ _null_ _null_ _null_ hash_numeric_extended _null_ _null_ _null_ )
+insert ( 328 hashmacaddr8 11 10 12 1 0 0 0 f f f t f i s 1 0 23 774 _null_ _null_ _null_ _null_ _null_ hashmacaddr8 _null_ _null_ _null_ )
+insert ( 781 hashmacaddr8extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "774 20" _null_ _null_ _null_ _null_ _null_ hashmacaddr8extended _null_ _null_ _null_ )
+insert ( 438 num_nulls 11 10 12 1 0 2276 0 f f f f f i s 1 0 23 2276 "{2276}" "{v}" _null_ _null_ _null_ pg_num_nulls _null_ _null_ _null_ )
+insert ( 440 num_nonnulls 11 10 12 1 0 2276 0 f f f f f i s 1 0 23 2276 "{2276}" "{v}" _null_ _null_ _null_ pg_num_nonnulls _null_ _null_ _null_ )
+insert ( 458 text_larger 11 10 12 1 0 0 0 f f t t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ text_larger _null_ _null_ _null_ )
+insert ( 459 text_smaller 11 10 12 1 0 0 0 f f t t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ text_smaller _null_ _null_ _null_ )
+insert ( 460 int8in 11 10 12 1 0 0 0 f f f t f i s 1 0 20 2275 _null_ _null_ _null_ _null_ _null_ int8in _null_ _null_ _null_ )
+insert ( 461 int8out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 20 _null_ _null_ _null_ _null_ _null_ int8out _null_ _null_ _null_ )
+insert ( 462 int8um 11 10 12 1 0 0 0 f f f t f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ int8um _null_ _null_ _null_ )
+insert ( 463 int8pl 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8pl _null_ _null_ _null_ )
+insert ( 464 int8mi 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8mi _null_ _null_ _null_ )
+insert ( 465 int8mul 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8mul _null_ _null_ _null_ )
+insert ( 466 int8div 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8div _null_ _null_ _null_ )
+insert ( 467 int8eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 20" _null_ _null_ _null_ _null_ _null_ int8eq _null_ _null_ _null_ )
+insert ( 468 int8ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 20" _null_ _null_ _null_ _null_ _null_ int8ne _null_ _null_ _null_ )
+insert ( 469 int8lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 20" _null_ _null_ _null_ _null_ _null_ int8lt _null_ _null_ _null_ )
+insert ( 470 int8gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 20" _null_ _null_ _null_ _null_ _null_ int8gt _null_ _null_ _null_ )
+insert ( 471 int8le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 20" _null_ _null_ _null_ _null_ _null_ int8le _null_ _null_ _null_ )
+insert ( 472 int8ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 20" _null_ _null_ _null_ _null_ _null_ int8ge _null_ _null_ _null_ )
+insert ( 474 int84eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 23" _null_ _null_ _null_ _null_ _null_ int84eq _null_ _null_ _null_ )
+insert ( 475 int84ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 23" _null_ _null_ _null_ _null_ _null_ int84ne _null_ _null_ _null_ )
+insert ( 476 int84lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 23" _null_ _null_ _null_ _null_ _null_ int84lt _null_ _null_ _null_ )
+insert ( 477 int84gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 23" _null_ _null_ _null_ _null_ _null_ int84gt _null_ _null_ _null_ )
+insert ( 478 int84le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 23" _null_ _null_ _null_ _null_ _null_ int84le _null_ _null_ _null_ )
+insert ( 479 int84ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 23" _null_ _null_ _null_ _null_ _null_ int84ge _null_ _null_ _null_ )
+insert ( 480 int4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 20 _null_ _null_ _null_ _null_ _null_ int84 _null_ _null_ _null_ )
+insert ( 481 int8 11 10 12 1 0 0 0 f f f t f i s 1 0 20 23 _null_ _null_ _null_ _null_ _null_ int48 _null_ _null_ _null_ )
+insert ( 482 float8 11 10 12 1 0 0 0 f f f t f i s 1 0 701 20 _null_ _null_ _null_ _null_ _null_ i8tod _null_ _null_ _null_ )
+insert ( 483 int8 11 10 12 1 0 0 0 f f f t f i s 1 0 20 701 _null_ _null_ _null_ _null_ _null_ dtoi8 _null_ _null_ _null_ )
+insert ( 626 hash_array 11 10 12 1 0 0 0 f f f t f i s 1 0 23 2277 _null_ _null_ _null_ _null_ _null_ hash_array _null_ _null_ _null_ )
+insert ( 782 hash_array_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "2277 20" _null_ _null_ _null_ _null_ _null_ hash_array_extended _null_ _null_ _null_ )
+insert ( 652 float4 11 10 12 1 0 0 0 f f f t f i s 1 0 700 20 _null_ _null_ _null_ _null_ _null_ i8tof _null_ _null_ _null_ )
+insert ( 653 int8 11 10 12 1 0 0 0 f f f t f i s 1 0 20 700 _null_ _null_ _null_ _null_ _null_ ftoi8 _null_ _null_ _null_ )
+insert ( 714 int2 11 10 12 1 0 0 0 f f f t f i s 1 0 21 20 _null_ _null_ _null_ _null_ _null_ int82 _null_ _null_ _null_ )
+insert ( 754 int8 11 10 12 1 0 0 0 f f f t f i s 1 0 20 21 _null_ _null_ _null_ _null_ _null_ int28 _null_ _null_ _null_ )
+insert ( 655 namelt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 19" _null_ _null_ _null_ _null_ _null_ namelt _null_ _null_ _null_ )
+insert ( 656 namele 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 19" _null_ _null_ _null_ _null_ _null_ namele _null_ _null_ _null_ )
+insert ( 657 namegt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 19" _null_ _null_ _null_ _null_ _null_ namegt _null_ _null_ _null_ )
+insert ( 658 namege 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 19" _null_ _null_ _null_ _null_ _null_ namege _null_ _null_ _null_ )
+insert ( 659 namene 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "19 19" _null_ _null_ _null_ _null_ _null_ namene _null_ _null_ _null_ )
+insert ( 668 bpchar 11 10 12 1 0 0 0 f f f t f i s 3 0 1042 "1042 23 16" _null_ _null_ _null_ _null_ _null_ bpchar _null_ _null_ _null_ )
+insert ( 3097 varchar_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ varchar_support _null_ _null_ _null_ )
+insert ( 669 varchar 11 10 12 1 0 0 3097 f f f t f i s 3 0 1043 "1043 23 16" _null_ _null_ _null_ _null_ _null_ varchar _null_ _null_ _null_ )
+insert ( 619 oidvectorne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "30 30" _null_ _null_ _null_ _null_ _null_ oidvectorne _null_ _null_ _null_ )
+insert ( 677 oidvectorlt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "30 30" _null_ _null_ _null_ _null_ _null_ oidvectorlt _null_ _null_ _null_ )
+insert ( 678 oidvectorle 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "30 30" _null_ _null_ _null_ _null_ _null_ oidvectorle _null_ _null_ _null_ )
+insert ( 679 oidvectoreq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "30 30" _null_ _null_ _null_ _null_ _null_ oidvectoreq _null_ _null_ _null_ )
+insert ( 680 oidvectorge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "30 30" _null_ _null_ _null_ _null_ _null_ oidvectorge _null_ _null_ _null_ )
+insert ( 681 oidvectorgt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "30 30" _null_ _null_ _null_ _null_ _null_ oidvectorgt _null_ _null_ _null_ )
+insert ( 710 getpgusername 11 10 12 1 0 0 0 f f f t f s s 0 0 19 "" _null_ _null_ _null_ _null_ _null_ current_user _null_ _null_ _null_ )
+insert ( 716 oidlt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oidlt _null_ _null_ _null_ )
+insert ( 717 oidle 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oidle _null_ _null_ _null_ )
+insert ( 720 octet_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 17 _null_ _null_ _null_ _null_ _null_ byteaoctetlen _null_ _null_ _null_ )
+insert ( 721 get_byte 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "17 23" _null_ _null_ _null_ _null_ _null_ byteaGetByte _null_ _null_ _null_ )
+insert ( 722 set_byte 11 10 12 1 0 0 0 f f f t f i s 3 0 17 "17 23 23" _null_ _null_ _null_ _null_ _null_ byteaSetByte _null_ _null_ _null_ )
+insert ( 723 get_bit 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "17 20" _null_ _null_ _null_ _null_ _null_ byteaGetBit _null_ _null_ _null_ )
+insert ( 724 set_bit 11 10 12 1 0 0 0 f f f t f i s 3 0 17 "17 20 23" _null_ _null_ _null_ _null_ _null_ byteaSetBit _null_ _null_ _null_ )
+insert ( 749 overlay 11 10 12 1 0 0 0 f f f t f i s 4 0 17 "17 17 23 23" _null_ _null_ _null_ _null_ _null_ byteaoverlay _null_ _null_ _null_ )
+insert ( 752 overlay 11 10 12 1 0 0 0 f f f t f i s 3 0 17 "17 17 23" _null_ _null_ _null_ _null_ _null_ byteaoverlay_no_len _null_ _null_ _null_ )
+insert ( 725 dist_pl 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "600 628" _null_ _null_ _null_ _null_ _null_ dist_pl _null_ _null_ _null_ )
+insert ( 702 dist_lp 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "628 600" _null_ _null_ _null_ _null_ _null_ dist_lp _null_ _null_ _null_ )
+insert ( 726 dist_lb 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "628 603" _null_ _null_ _null_ _null_ _null_ dist_lb _null_ _null_ _null_ )
+insert ( 703 dist_bl 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "603 628" _null_ _null_ _null_ _null_ _null_ dist_bl _null_ _null_ _null_ )
+insert ( 727 dist_sl 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "601 628" _null_ _null_ _null_ _null_ _null_ dist_sl _null_ _null_ _null_ )
+insert ( 704 dist_ls 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "628 601" _null_ _null_ _null_ _null_ _null_ dist_ls _null_ _null_ _null_ )
+insert ( 728 dist_cpoly 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "718 604" _null_ _null_ _null_ _null_ _null_ dist_cpoly _null_ _null_ _null_ )
+insert ( 785 dist_polyc 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "604 718" _null_ _null_ _null_ _null_ _null_ dist_polyc _null_ _null_ _null_ )
+insert ( 729 poly_distance 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "604 604" _null_ _null_ _null_ _null_ _null_ poly_distance _null_ _null_ _null_ )
+insert ( 3275 dist_ppoly 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "600 604" _null_ _null_ _null_ _null_ _null_ dist_ppoly _null_ _null_ _null_ )
+insert ( 3292 dist_polyp 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "604 600" _null_ _null_ _null_ _null_ _null_ dist_polyp _null_ _null_ _null_ )
+insert ( 3290 dist_cpoint 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "718 600" _null_ _null_ _null_ _null_ _null_ dist_cpoint _null_ _null_ _null_ )
+insert ( 740 text_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ text_lt _null_ _null_ _null_ )
+insert ( 741 text_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ text_le _null_ _null_ _null_ )
+insert ( 742 text_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ text_gt _null_ _null_ _null_ )
+insert ( 743 text_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ text_ge _null_ _null_ _null_ )
+insert ( 745 current_user 11 10 12 1 0 0 0 f f f t f s s 0 0 19 "" _null_ _null_ _null_ _null_ _null_ current_user _null_ _null_ _null_ )
+insert ( 746 session_user 11 10 12 1 0 0 0 f f f t f s s 0 0 19 "" _null_ _null_ _null_ _null_ _null_ session_user _null_ _null_ _null_ )
+insert ( 744 array_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2277 2277" _null_ _null_ _null_ _null_ _null_ array_eq _null_ _null_ _null_ )
+insert ( 390 array_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2277 2277" _null_ _null_ _null_ _null_ _null_ array_ne _null_ _null_ _null_ )
+insert ( 391 array_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2277 2277" _null_ _null_ _null_ _null_ _null_ array_lt _null_ _null_ _null_ )
+insert ( 392 array_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2277 2277" _null_ _null_ _null_ _null_ _null_ array_gt _null_ _null_ _null_ )
+insert ( 393 array_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2277 2277" _null_ _null_ _null_ _null_ _null_ array_le _null_ _null_ _null_ )
+insert ( 396 array_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2277 2277" _null_ _null_ _null_ _null_ _null_ array_ge _null_ _null_ _null_ )
+insert ( 747 array_dims 11 10 12 1 0 0 0 f f f t f i s 1 0 25 2277 _null_ _null_ _null_ _null_ _null_ array_dims _null_ _null_ _null_ )
+insert ( 748 array_ndims 11 10 12 1 0 0 0 f f f t f i s 1 0 23 2277 _null_ _null_ _null_ _null_ _null_ array_ndims _null_ _null_ _null_ )
+insert ( 750 array_in 11 10 12 1 0 0 0 f f f t f s s 3 0 2277 "2275 26 23" _null_ _null_ _null_ _null_ _null_ array_in _null_ _null_ _null_ )
+insert ( 751 array_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 2277 _null_ _null_ _null_ _null_ _null_ array_out _null_ _null_ _null_ )
+insert ( 2091 array_lower 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "2277 23" _null_ _null_ _null_ _null_ _null_ array_lower _null_ _null_ _null_ )
+insert ( 2092 array_upper 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "2277 23" _null_ _null_ _null_ _null_ _null_ array_upper _null_ _null_ _null_ )
+insert ( 2176 array_length 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "2277 23" _null_ _null_ _null_ _null_ _null_ array_length _null_ _null_ _null_ )
+insert ( 3179 cardinality 11 10 12 1 0 0 0 f f f t f i s 1 0 23 2277 _null_ _null_ _null_ _null_ _null_ array_cardinality _null_ _null_ _null_ )
+insert ( 378 array_append 11 10 12 1 0 0 0 f f f f f i s 2 0 2277 "2277 2283" _null_ _null_ _null_ _null_ _null_ array_append _null_ _null_ _null_ )
+insert ( 379 array_prepend 11 10 12 1 0 0 0 f f f f f i s 2 0 2277 "2283 2277" _null_ _null_ _null_ _null_ _null_ array_prepend _null_ _null_ _null_ )
+insert ( 383 array_cat 11 10 12 1 0 0 0 f f f f f i s 2 0 2277 "2277 2277" _null_ _null_ _null_ _null_ _null_ array_cat _null_ _null_ _null_ )
+insert ( 394 string_to_array 11 10 12 1 0 0 0 f f f f f i s 2 0 1009 "25 25" _null_ _null_ _null_ _null_ _null_ text_to_array _null_ _null_ _null_ )
+insert ( 395 array_to_string 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "2277 25" _null_ _null_ _null_ _null_ _null_ array_to_text _null_ _null_ _null_ )
+insert ( 376 string_to_array 11 10 12 1 0 0 0 f f f f f i s 3 0 1009 "25 25 25" _null_ _null_ _null_ _null_ _null_ text_to_array_null _null_ _null_ _null_ )
+insert ( 384 array_to_string 11 10 12 1 0 0 0 f f f f f s s 3 0 25 "2277 25 25" _null_ _null_ _null_ _null_ _null_ array_to_text_null _null_ _null_ _null_ )
+insert ( 515 array_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 2277 "2277 2277" _null_ _null_ _null_ _null_ _null_ array_larger _null_ _null_ _null_ )
+insert ( 516 array_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 2277 "2277 2277" _null_ _null_ _null_ _null_ _null_ array_smaller _null_ _null_ _null_ )
+insert ( 3277 array_position 11 10 12 1 0 0 0 f f f f f i s 2 0 23 "2277 2283" _null_ _null_ _null_ _null_ _null_ array_position _null_ _null_ _null_ )
+insert ( 3278 array_position 11 10 12 1 0 0 0 f f f f f i s 3 0 23 "2277 2283 23" _null_ _null_ _null_ _null_ _null_ array_position_start _null_ _null_ _null_ )
+insert ( 3279 array_positions 11 10 12 1 0 0 0 f f f f f i s 2 0 1007 "2277 2283" _null_ _null_ _null_ _null_ _null_ array_positions _null_ _null_ _null_ )
+insert ( 1191 generate_subscripts 11 10 12 1 1000 0 0 f f f t t i s 3 0 23 "2277 23 16" _null_ _null_ _null_ _null_ _null_ generate_subscripts _null_ _null_ _null_ )
+insert ( 1192 generate_subscripts 11 10 12 1 1000 0 0 f f f t t i s 2 0 23 "2277 23" _null_ _null_ _null_ _null_ _null_ generate_subscripts_nodir _null_ _null_ _null_ )
+insert ( 1193 array_fill 11 10 12 1 0 0 0 f f f f f i s 2 0 2277 "2283 1007" _null_ _null_ _null_ _null_ _null_ array_fill _null_ _null_ _null_ )
+insert ( 1286 array_fill 11 10 12 1 0 0 0 f f f f f i s 3 0 2277 "2283 1007 1007" _null_ _null_ _null_ _null_ _null_ array_fill_with_lower_bounds _null_ _null_ _null_ )
+insert ( 2331 unnest 11 10 12 1 100 0 3996 f f f t t i s 1 0 2283 2277 _null_ _null_ _null_ _null_ _null_ array_unnest _null_ _null_ _null_ )
+insert ( 3996 array_unnest_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ array_unnest_support _null_ _null_ _null_ )
+insert ( 3167 array_remove 11 10 12 1 0 0 0 f f f f f i s 2 0 2277 "2277 2283" _null_ _null_ _null_ _null_ _null_ array_remove _null_ _null_ _null_ )
+insert ( 3168 array_replace 11 10 12 1 0 0 0 f f f f f i s 3 0 2277 "2277 2283 2283" _null_ _null_ _null_ _null_ _null_ array_replace _null_ _null_ _null_ )
+insert ( 2333 array_agg_transfn 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 2776" _null_ _null_ _null_ _null_ _null_ array_agg_transfn _null_ _null_ _null_ )
+insert ( 2334 array_agg_finalfn 11 10 12 1 0 0 0 f f f f f i s 2 0 2277 "2281 2776" _null_ _null_ _null_ _null_ _null_ array_agg_finalfn _null_ _null_ _null_ )
+insert ( 2335 array_agg 11 10 12 1 0 0 0 a f f f f i s 1 0 2277 2776 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 4051 array_agg_array_transfn 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 2277" _null_ _null_ _null_ _null_ _null_ array_agg_array_transfn _null_ _null_ _null_ )
+insert ( 4052 array_agg_array_finalfn 11 10 12 1 0 0 0 f f f f f i s 2 0 2277 "2281 2277" _null_ _null_ _null_ _null_ _null_ array_agg_array_finalfn _null_ _null_ _null_ )
+insert ( 4053 array_agg 11 10 12 1 0 0 0 a f f f f i s 1 0 2277 2277 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3218 width_bucket 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "2283 2277" _null_ _null_ _null_ _null_ _null_ width_bucket_array _null_ _null_ _null_ )
+insert ( 3816 array_typanalyze 11 10 12 1 0 0 0 f f f t f s s 1 0 16 2281 _null_ _null_ _null_ _null_ _null_ array_typanalyze _null_ _null_ _null_ )
+insert ( 3817 arraycontsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ arraycontsel _null_ _null_ _null_ )
+insert ( 3818 arraycontjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ arraycontjoinsel _null_ _null_ _null_ )
+insert ( 764 lo_import 11 10 12 1 0 0 0 f f f t f v u 1 0 26 25 _null_ _null_ _null_ _null_ _null_ be_lo_import _null_ _null_ _null_ )
+insert ( 767 lo_import 11 10 12 1 0 0 0 f f f t f v u 2 0 26 "25 26" _null_ _null_ _null_ _null_ _null_ be_lo_import_with_oid _null_ _null_ _null_ )
+insert ( 765 lo_export 11 10 12 1 0 0 0 f f f t f v u 2 0 23 "26 25" _null_ _null_ _null_ _null_ _null_ be_lo_export _null_ _null_ _null_ )
+insert ( 766 int4inc 11 10 12 1 0 0 0 f f f t f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ int4inc _null_ _null_ _null_ )
+insert ( 768 int4larger 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4larger _null_ _null_ _null_ )
+insert ( 769 int4smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4smaller _null_ _null_ _null_ )
+insert ( 770 int2larger 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2larger _null_ _null_ _null_ )
+insert ( 771 int2smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2smaller _null_ _null_ _null_ )
+insert ( 846 cash_mul_flt4 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 700" _null_ _null_ _null_ _null_ _null_ cash_mul_flt4 _null_ _null_ _null_ )
+insert ( 847 cash_div_flt4 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 700" _null_ _null_ _null_ _null_ _null_ cash_div_flt4 _null_ _null_ _null_ )
+insert ( 848 flt4_mul_cash 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "700 790" _null_ _null_ _null_ _null_ _null_ flt4_mul_cash _null_ _null_ _null_ )
+insert ( 849 position 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "25 25" _null_ _null_ _null_ _null_ _null_ textpos _null_ _null_ _null_ )
+insert ( 850 textlike 11 10 12 1 0 0 1023 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ textlike _null_ _null_ _null_ )
+insert ( 1023 textlike_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ textlike_support _null_ _null_ _null_ )
+insert ( 851 textnlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ textnlike _null_ _null_ _null_ )
+insert ( 852 int48eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 20" _null_ _null_ _null_ _null_ _null_ int48eq _null_ _null_ _null_ )
+insert ( 853 int48ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 20" _null_ _null_ _null_ _null_ _null_ int48ne _null_ _null_ _null_ )
+insert ( 854 int48lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 20" _null_ _null_ _null_ _null_ _null_ int48lt _null_ _null_ _null_ )
+insert ( 855 int48gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 20" _null_ _null_ _null_ _null_ _null_ int48gt _null_ _null_ _null_ )
+insert ( 856 int48le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 20" _null_ _null_ _null_ _null_ _null_ int48le _null_ _null_ _null_ )
+insert ( 857 int48ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "23 20" _null_ _null_ _null_ _null_ _null_ int48ge _null_ _null_ _null_ )
+insert ( 858 namelike 11 10 12 1 0 0 1023 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ namelike _null_ _null_ _null_ )
+insert ( 859 namenlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ namenlike _null_ _null_ _null_ )
+insert ( 860 bpchar 11 10 12 1 0 0 0 f f f t f i s 1 0 1042 18 _null_ _null_ _null_ _null_ _null_ char_bpchar _null_ _null_ _null_ )
+insert ( 861 current_database 11 10 12 1 0 0 0 f f f t f s s 0 0 19 "" _null_ _null_ _null_ _null_ _null_ current_database _null_ _null_ _null_ )
+insert ( 817 current_query 11 10 12 1 0 0 0 f f f f f v r 0 0 25 "" _null_ _null_ _null_ _null_ _null_ current_query _null_ _null_ _null_ )
+insert ( 3399 int8_mul_cash 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "20 790" _null_ _null_ _null_ _null_ _null_ int8_mul_cash _null_ _null_ _null_ )
+insert ( 862 int4_mul_cash 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "23 790" _null_ _null_ _null_ _null_ _null_ int4_mul_cash _null_ _null_ _null_ )
+insert ( 863 int2_mul_cash 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "21 790" _null_ _null_ _null_ _null_ _null_ int2_mul_cash _null_ _null_ _null_ )
+insert ( 3344 cash_mul_int8 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 20" _null_ _null_ _null_ _null_ _null_ cash_mul_int8 _null_ _null_ _null_ )
+insert ( 3345 cash_div_int8 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 20" _null_ _null_ _null_ _null_ _null_ cash_div_int8 _null_ _null_ _null_ )
+insert ( 864 cash_mul_int4 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 23" _null_ _null_ _null_ _null_ _null_ cash_mul_int4 _null_ _null_ _null_ )
+insert ( 865 cash_div_int4 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 23" _null_ _null_ _null_ _null_ _null_ cash_div_int4 _null_ _null_ _null_ )
+insert ( 866 cash_mul_int2 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 21" _null_ _null_ _null_ _null_ _null_ cash_mul_int2 _null_ _null_ _null_ )
+insert ( 867 cash_div_int2 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 21" _null_ _null_ _null_ _null_ _null_ cash_div_int2 _null_ _null_ _null_ )
+insert ( 886 cash_in 11 10 12 1 0 0 0 f f f t f s s 1 0 790 2275 _null_ _null_ _null_ _null_ _null_ cash_in _null_ _null_ _null_ )
+insert ( 887 cash_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 790 _null_ _null_ _null_ _null_ _null_ cash_out _null_ _null_ _null_ )
+insert ( 888 cash_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "790 790" _null_ _null_ _null_ _null_ _null_ cash_eq _null_ _null_ _null_ )
+insert ( 889 cash_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "790 790" _null_ _null_ _null_ _null_ _null_ cash_ne _null_ _null_ _null_ )
+insert ( 890 cash_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "790 790" _null_ _null_ _null_ _null_ _null_ cash_lt _null_ _null_ _null_ )
+insert ( 891 cash_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "790 790" _null_ _null_ _null_ _null_ _null_ cash_le _null_ _null_ _null_ )
+insert ( 892 cash_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "790 790" _null_ _null_ _null_ _null_ _null_ cash_gt _null_ _null_ _null_ )
+insert ( 893 cash_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "790 790" _null_ _null_ _null_ _null_ _null_ cash_ge _null_ _null_ _null_ )
+insert ( 894 cash_pl 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 790" _null_ _null_ _null_ _null_ _null_ cash_pl _null_ _null_ _null_ )
+insert ( 895 cash_mi 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 790" _null_ _null_ _null_ _null_ _null_ cash_mi _null_ _null_ _null_ )
+insert ( 896 cash_mul_flt8 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 701" _null_ _null_ _null_ _null_ _null_ cash_mul_flt8 _null_ _null_ _null_ )
+insert ( 897 cash_div_flt8 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 701" _null_ _null_ _null_ _null_ _null_ cash_div_flt8 _null_ _null_ _null_ )
+insert ( 898 cashlarger 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 790" _null_ _null_ _null_ _null_ _null_ cashlarger _null_ _null_ _null_ )
+insert ( 899 cashsmaller 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "790 790" _null_ _null_ _null_ _null_ _null_ cashsmaller _null_ _null_ _null_ )
+insert ( 919 flt8_mul_cash 11 10 12 1 0 0 0 f f f t f i s 2 0 790 "701 790" _null_ _null_ _null_ _null_ _null_ flt8_mul_cash _null_ _null_ _null_ )
+insert ( 935 cash_words 11 10 12 1 0 0 0 f f f t f i s 1 0 25 790 _null_ _null_ _null_ _null_ _null_ cash_words _null_ _null_ _null_ )
+insert ( 3822 cash_div_cash 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "790 790" _null_ _null_ _null_ _null_ _null_ cash_div_cash _null_ _null_ _null_ )
+insert ( 3823 numeric 11 10 12 1 0 0 0 f f f t f s s 1 0 1700 790 _null_ _null_ _null_ _null_ _null_ cash_numeric _null_ _null_ _null_ )
+insert ( 3824 money 11 10 12 1 0 0 0 f f f t f s s 1 0 790 1700 _null_ _null_ _null_ _null_ _null_ numeric_cash _null_ _null_ _null_ )
+insert ( 3811 money 11 10 12 1 0 0 0 f f f t f s s 1 0 790 23 _null_ _null_ _null_ _null_ _null_ int4_cash _null_ _null_ _null_ )
+insert ( 3812 money 11 10 12 1 0 0 0 f f f t f s s 1 0 790 20 _null_ _null_ _null_ _null_ _null_ int8_cash _null_ _null_ _null_ )
+insert ( 940 mod 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2mod _null_ _null_ _null_ )
+insert ( 941 mod 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4mod _null_ _null_ _null_ )
+insert ( 945 int8mod 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8mod _null_ _null_ _null_ )
+insert ( 947 mod 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8mod _null_ _null_ _null_ )
+insert ( 5044 gcd 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4gcd _null_ _null_ _null_ )
+insert ( 5045 gcd 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8gcd _null_ _null_ _null_ )
+insert ( 5046 lcm 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4lcm _null_ _null_ _null_ )
+insert ( 5047 lcm 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8lcm _null_ _null_ _null_ )
+insert ( 944 char 11 10 12 1 0 0 0 f f f t f i s 1 0 18 25 _null_ _null_ _null_ _null_ _null_ text_char _null_ _null_ _null_ )
+insert ( 946 text 11 10 12 1 0 0 0 f f f t f i s 1 0 25 18 _null_ _null_ _null_ _null_ _null_ char_text _null_ _null_ _null_ )
+insert ( 952 lo_open 11 10 12 1 0 0 0 f f f t f v u 2 0 23 "26 23" _null_ _null_ _null_ _null_ _null_ be_lo_open _null_ _null_ _null_ )
+insert ( 953 lo_close 11 10 12 1 0 0 0 f f f t f v u 1 0 23 23 _null_ _null_ _null_ _null_ _null_ be_lo_close _null_ _null_ _null_ )
+insert ( 954 loread 11 10 12 1 0 0 0 f f f t f v u 2 0 17 "23 23" _null_ _null_ _null_ _null_ _null_ be_loread _null_ _null_ _null_ )
+insert ( 955 lowrite 11 10 12 1 0 0 0 f f f t f v u 2 0 23 "23 17" _null_ _null_ _null_ _null_ _null_ be_lowrite _null_ _null_ _null_ )
+insert ( 956 lo_lseek 11 10 12 1 0 0 0 f f f t f v u 3 0 23 "23 23 23" _null_ _null_ _null_ _null_ _null_ be_lo_lseek _null_ _null_ _null_ )
+insert ( 3170 lo_lseek64 11 10 12 1 0 0 0 f f f t f v u 3 0 20 "23 20 23" _null_ _null_ _null_ _null_ _null_ be_lo_lseek64 _null_ _null_ _null_ )
+insert ( 957 lo_creat 11 10 12 1 0 0 0 f f f t f v u 1 0 26 23 _null_ _null_ _null_ _null_ _null_ be_lo_creat _null_ _null_ _null_ )
+insert ( 715 lo_create 11 10 12 1 0 0 0 f f f t f v u 1 0 26 26 _null_ _null_ _null_ _null_ _null_ be_lo_create _null_ _null_ _null_ )
+insert ( 958 lo_tell 11 10 12 1 0 0 0 f f f t f v u 1 0 23 23 _null_ _null_ _null_ _null_ _null_ be_lo_tell _null_ _null_ _null_ )
+insert ( 3171 lo_tell64 11 10 12 1 0 0 0 f f f t f v u 1 0 20 23 _null_ _null_ _null_ _null_ _null_ be_lo_tell64 _null_ _null_ _null_ )
+insert ( 1004 lo_truncate 11 10 12 1 0 0 0 f f f t f v u 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ be_lo_truncate _null_ _null_ _null_ )
+insert ( 3172 lo_truncate64 11 10 12 1 0 0 0 f f f t f v u 2 0 23 "23 20" _null_ _null_ _null_ _null_ _null_ be_lo_truncate64 _null_ _null_ _null_ )
+insert ( 3457 lo_from_bytea 11 10 12 1 0 0 0 f f f t f v u 2 0 26 "26 17" _null_ _null_ _null_ _null_ _null_ be_lo_from_bytea _null_ _null_ _null_ )
+insert ( 3458 lo_get 11 10 12 1 0 0 0 f f f t f v u 1 0 17 26 _null_ _null_ _null_ _null_ _null_ be_lo_get _null_ _null_ _null_ )
+insert ( 3459 lo_get 11 10 12 1 0 0 0 f f f t f v u 3 0 17 "26 20 23" _null_ _null_ _null_ _null_ _null_ be_lo_get_fragment _null_ _null_ _null_ )
+insert ( 3460 lo_put 11 10 12 1 0 0 0 f f f t f v u 3 0 2278 "26 20 17" _null_ _null_ _null_ _null_ _null_ be_lo_put _null_ _null_ _null_ )
+insert ( 959 on_pl 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 628" _null_ _null_ _null_ _null_ _null_ on_pl _null_ _null_ _null_ )
+insert ( 960 on_sl 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "601 628" _null_ _null_ _null_ _null_ _null_ on_sl _null_ _null_ _null_ )
+insert ( 961 close_pl 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "600 628" _null_ _null_ _null_ _null_ _null_ close_pl _null_ _null_ _null_ )
+insert ( 962 close_sl 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "601 628" _null_ _null_ _null_ _null_ _null_ close_sl _null_ _null_ _null_ )
+insert ( 963 close_lb 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "628 603" _null_ _null_ _null_ _null_ _null_ close_lb _null_ _null_ _null_ )
+insert ( 964 lo_unlink 11 10 12 1 0 0 0 f f f t f v u 1 0 23 26 _null_ _null_ _null_ _null_ _null_ be_lo_unlink _null_ _null_ _null_ )
+insert ( 973 path_inter 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "602 602" _null_ _null_ _null_ _null_ _null_ path_inter _null_ _null_ _null_ )
+insert ( 975 area 11 10 12 1 0 0 0 f f f t f i s 1 0 701 603 _null_ _null_ _null_ _null_ _null_ box_area _null_ _null_ _null_ )
+insert ( 976 width 11 10 12 1 0 0 0 f f f t f i s 1 0 701 603 _null_ _null_ _null_ _null_ _null_ box_width _null_ _null_ _null_ )
+insert ( 977 height 11 10 12 1 0 0 0 f f f t f i s 1 0 701 603 _null_ _null_ _null_ _null_ _null_ box_height _null_ _null_ _null_ )
+insert ( 978 box_distance 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "603 603" _null_ _null_ _null_ _null_ _null_ box_distance _null_ _null_ _null_ )
+insert ( 979 area 11 10 12 1 0 0 0 f f f t f i s 1 0 701 602 _null_ _null_ _null_ _null_ _null_ path_area _null_ _null_ _null_ )
+insert ( 980 box_intersect 11 10 12 1 0 0 0 f f f t f i s 2 0 603 "603 603" _null_ _null_ _null_ _null_ _null_ box_intersect _null_ _null_ _null_ )
+insert ( 4067 bound_box 11 10 12 1 0 0 0 f f f t f i s 2 0 603 "603 603" _null_ _null_ _null_ _null_ _null_ boxes_bound_box _null_ _null_ _null_ )
+insert ( 981 diagonal 11 10 12 1 0 0 0 f f f t f i s 1 0 601 603 _null_ _null_ _null_ _null_ _null_ box_diagonal _null_ _null_ _null_ )
+insert ( 982 path_n_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "602 602" _null_ _null_ _null_ _null_ _null_ path_n_lt _null_ _null_ _null_ )
+insert ( 983 path_n_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "602 602" _null_ _null_ _null_ _null_ _null_ path_n_gt _null_ _null_ _null_ )
+insert ( 984 path_n_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "602 602" _null_ _null_ _null_ _null_ _null_ path_n_eq _null_ _null_ _null_ )
+insert ( 985 path_n_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "602 602" _null_ _null_ _null_ _null_ _null_ path_n_le _null_ _null_ _null_ )
+insert ( 986 path_n_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "602 602" _null_ _null_ _null_ _null_ _null_ path_n_ge _null_ _null_ _null_ )
+insert ( 987 path_length 11 10 12 1 0 0 0 f f f t f i s 1 0 701 602 _null_ _null_ _null_ _null_ _null_ path_length _null_ _null_ _null_ )
+insert ( 988 point_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_ne _null_ _null_ _null_ )
+insert ( 989 point_vert 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_vert _null_ _null_ _null_ )
+insert ( 990 point_horiz 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_horiz _null_ _null_ _null_ )
+insert ( 991 point_distance 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "600 600" _null_ _null_ _null_ _null_ _null_ point_distance _null_ _null_ _null_ )
+insert ( 992 slope 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "600 600" _null_ _null_ _null_ _null_ _null_ point_slope _null_ _null_ _null_ )
+insert ( 993 lseg 11 10 12 1 0 0 0 f f f t f i s 2 0 601 "600 600" _null_ _null_ _null_ _null_ _null_ lseg_construct _null_ _null_ _null_ )
+insert ( 994 lseg_intersect 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_intersect _null_ _null_ _null_ )
+insert ( 995 lseg_parallel 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_parallel _null_ _null_ _null_ )
+insert ( 996 lseg_perp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_perp _null_ _null_ _null_ )
+insert ( 997 lseg_vertical 11 10 12 1 0 0 0 f f f t f i s 1 0 16 601 _null_ _null_ _null_ _null_ _null_ lseg_vertical _null_ _null_ _null_ )
+insert ( 998 lseg_horizontal 11 10 12 1 0 0 0 f f f t f i s 1 0 16 601 _null_ _null_ _null_ _null_ _null_ lseg_horizontal _null_ _null_ _null_ )
+insert ( 999 lseg_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_eq _null_ _null_ _null_ )
+insert ( 1026 timezone 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "1186 1184" _null_ _null_ _null_ _null_ _null_ timestamptz_izone _null_ _null_ _null_ )
+insert ( 1031 aclitemin 11 10 12 1 0 0 0 f f f t f s s 1 0 1033 2275 _null_ _null_ _null_ _null_ _null_ aclitemin _null_ _null_ _null_ )
+insert ( 1032 aclitemout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 1033 _null_ _null_ _null_ _null_ _null_ aclitemout _null_ _null_ _null_ )
+insert ( 1035 aclinsert 11 10 12 1 0 0 0 f f f t f i s 2 0 1034 "1034 1033" _null_ _null_ _null_ _null_ _null_ aclinsert _null_ _null_ _null_ )
+insert ( 1036 aclremove 11 10 12 1 0 0 0 f f f t f i s 2 0 1034 "1034 1033" _null_ _null_ _null_ _null_ _null_ aclremove _null_ _null_ _null_ )
+insert ( 1037 aclcontains 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1034 1033" _null_ _null_ _null_ _null_ _null_ aclcontains _null_ _null_ _null_ )
+insert ( 1062 aclitemeq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1033 1033" _null_ _null_ _null_ _null_ _null_ aclitem_eq _null_ _null_ _null_ )
+insert ( 1365 makeaclitem 11 10 12 1 0 0 0 f f f t f i s 4 0 1033 "26 26 25 16" _null_ _null_ _null_ _null_ _null_ makeaclitem _null_ _null_ _null_ )
+insert ( 3943 acldefault 11 10 12 1 0 0 0 f f f t f i s 2 0 1034 "18 26" _null_ _null_ _null_ _null_ _null_ acldefault_sql _null_ _null_ _null_ )
+insert ( 1689 aclexplode 11 10 12 1 10 0 0 f f f t t s s 1 0 2249 1034 "{1034,26,26,25,16}" "{i,o,o,o,o}" "{acl,grantor,grantee,privilege_type,is_grantable}" _null_ _null_ aclexplode _null_ _null_ _null_ )
+insert ( 1044 bpcharin 11 10 12 1 0 0 0 f f f t f i s 3 0 1042 "2275 26 23" _null_ _null_ _null_ _null_ _null_ bpcharin _null_ _null_ _null_ )
+insert ( 1045 bpcharout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 1042 _null_ _null_ _null_ _null_ _null_ bpcharout _null_ _null_ _null_ )
+insert ( 2913 bpchartypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ bpchartypmodin _null_ _null_ _null_ )
+insert ( 2914 bpchartypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ bpchartypmodout _null_ _null_ _null_ )
+insert ( 1046 varcharin 11 10 12 1 0 0 0 f f f t f i s 3 0 1043 "2275 26 23" _null_ _null_ _null_ _null_ _null_ varcharin _null_ _null_ _null_ )
+insert ( 1047 varcharout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 1043 _null_ _null_ _null_ _null_ _null_ varcharout _null_ _null_ _null_ )
+insert ( 2915 varchartypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ varchartypmodin _null_ _null_ _null_ )
+insert ( 2916 varchartypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ varchartypmodout _null_ _null_ _null_ )
+insert ( 1048 bpchareq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpchareq _null_ _null_ _null_ )
+insert ( 1049 bpcharlt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpcharlt _null_ _null_ _null_ )
+insert ( 1050 bpcharle 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpcharle _null_ _null_ _null_ )
+insert ( 1051 bpchargt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpchargt _null_ _null_ _null_ )
+insert ( 1052 bpcharge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpcharge _null_ _null_ _null_ )
+insert ( 1053 bpcharne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpcharne _null_ _null_ _null_ )
+insert ( 1063 bpchar_larger 11 10 12 1 0 0 0 f f t t f i s 2 0 1042 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpchar_larger _null_ _null_ _null_ )
+insert ( 1064 bpchar_smaller 11 10 12 1 0 0 0 f f t t f i s 2 0 1042 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpchar_smaller _null_ _null_ _null_ )
+insert ( 1078 bpcharcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpcharcmp _null_ _null_ _null_ )
+insert ( 3328 bpchar_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ bpchar_sortsupport _null_ _null_ _null_ )
+insert ( 1080 hashbpchar 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1042 _null_ _null_ _null_ _null_ _null_ hashbpchar _null_ _null_ _null_ )
+insert ( 972 hashbpcharextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "1042 20" _null_ _null_ _null_ _null_ _null_ hashbpcharextended _null_ _null_ _null_ )
+insert ( 1081 format_type 11 10 12 1 0 0 0 f f f f f s s 2 0 25 "26 23" _null_ _null_ _null_ _null_ _null_ format_type _null_ _null_ _null_ )
+insert ( 1084 date_in 11 10 12 1 0 0 0 f f f t f s s 1 0 1082 2275 _null_ _null_ _null_ _null_ _null_ date_in _null_ _null_ _null_ )
+insert ( 1085 date_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 1082 _null_ _null_ _null_ _null_ _null_ date_out _null_ _null_ _null_ )
+insert ( 1086 date_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_eq _null_ _null_ _null_ )
+insert ( 1087 date_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_lt _null_ _null_ _null_ )
+insert ( 1088 date_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_le _null_ _null_ _null_ )
+insert ( 1089 date_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_gt _null_ _null_ _null_ )
+insert ( 1090 date_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_ge _null_ _null_ _null_ )
+insert ( 1091 date_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_ne _null_ _null_ _null_ )
+insert ( 1092 date_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_cmp _null_ _null_ _null_ )
+insert ( 3136 date_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ date_sortsupport _null_ _null_ _null_ )
+insert ( 4133 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "1082 1082 1186 16 16" _null_ _null_ _null_ _null_ _null_ in_range_date_interval _null_ _null_ _null_ )
+insert ( 1102 time_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_lt _null_ _null_ _null_ )
+insert ( 1103 time_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_le _null_ _null_ _null_ )
+insert ( 1104 time_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_gt _null_ _null_ _null_ )
+insert ( 1105 time_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_ge _null_ _null_ _null_ )
+insert ( 1106 time_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_ne _null_ _null_ _null_ )
+insert ( 1107 time_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_cmp _null_ _null_ _null_ )
+insert ( 1138 date_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 1082 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_larger _null_ _null_ _null_ )
+insert ( 1139 date_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 1082 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_smaller _null_ _null_ _null_ )
+insert ( 1140 date_mi 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "1082 1082" _null_ _null_ _null_ _null_ _null_ date_mi _null_ _null_ _null_ )
+insert ( 1141 date_pli 11 10 12 1 0 0 0 f f f t f i s 2 0 1082 "1082 23" _null_ _null_ _null_ _null_ _null_ date_pli _null_ _null_ _null_ )
+insert ( 1142 date_mii 11 10 12 1 0 0 0 f f f t f i s 2 0 1082 "1082 23" _null_ _null_ _null_ _null_ _null_ date_mii _null_ _null_ _null_ )
+insert ( 1143 time_in 11 10 12 1 0 0 0 f f f t f s s 3 0 1083 "2275 26 23" _null_ _null_ _null_ _null_ _null_ time_in _null_ _null_ _null_ )
+insert ( 1144 time_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 1083 _null_ _null_ _null_ _null_ _null_ time_out _null_ _null_ _null_ )
+insert ( 2909 timetypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ timetypmodin _null_ _null_ _null_ )
+insert ( 2910 timetypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ timetypmodout _null_ _null_ _null_ )
+insert ( 1145 time_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_eq _null_ _null_ _null_ )
+insert ( 1146 circle_add_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 718 "718 600" _null_ _null_ _null_ _null_ _null_ circle_add_pt _null_ _null_ _null_ )
+insert ( 1147 circle_sub_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 718 "718 600" _null_ _null_ _null_ _null_ _null_ circle_sub_pt _null_ _null_ _null_ )
+insert ( 1148 circle_mul_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 718 "718 600" _null_ _null_ _null_ _null_ _null_ circle_mul_pt _null_ _null_ _null_ )
+insert ( 1149 circle_div_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 718 "718 600" _null_ _null_ _null_ _null_ _null_ circle_div_pt _null_ _null_ _null_ )
+insert ( 1150 timestamptz_in 11 10 12 1 0 0 0 f f f t f s s 3 0 1184 "2275 26 23" _null_ _null_ _null_ _null_ _null_ timestamptz_in _null_ _null_ _null_ )
+insert ( 1151 timestamptz_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 1184 _null_ _null_ _null_ _null_ _null_ timestamptz_out _null_ _null_ _null_ )
+insert ( 2907 timestamptztypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ timestamptztypmodin _null_ _null_ _null_ )
+insert ( 2908 timestamptztypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ timestamptztypmodout _null_ _null_ _null_ )
+insert ( 1152 timestamptz_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_eq _null_ _null_ _null_ )
+insert ( 1153 timestamptz_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_ne _null_ _null_ _null_ )
+insert ( 1154 timestamptz_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_lt _null_ _null_ _null_ )
+insert ( 1155 timestamptz_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_le _null_ _null_ _null_ )
+insert ( 1156 timestamptz_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_ge _null_ _null_ _null_ )
+insert ( 1157 timestamptz_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_gt _null_ _null_ _null_ )
+insert ( 1158 to_timestamp 11 10 12 1 0 0 0 f f f t f i s 1 0 1184 701 _null_ _null_ _null_ _null_ _null_ float8_timestamptz _null_ _null_ _null_ )
+insert ( 1159 timezone 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "25 1184" _null_ _null_ _null_ _null_ _null_ timestamptz_zone _null_ _null_ _null_ )
+insert ( 1160 interval_in 11 10 12 1 0 0 0 f f f t f s s 3 0 1186 "2275 26 23" _null_ _null_ _null_ _null_ _null_ interval_in _null_ _null_ _null_ )
+insert ( 1161 interval_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 1186 _null_ _null_ _null_ _null_ _null_ interval_out _null_ _null_ _null_ )
+insert ( 2903 intervaltypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ intervaltypmodin _null_ _null_ _null_ )
+insert ( 2904 intervaltypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ intervaltypmodout _null_ _null_ _null_ )
+insert ( 1162 interval_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_eq _null_ _null_ _null_ )
+insert ( 1163 interval_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_ne _null_ _null_ _null_ )
+insert ( 1164 interval_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_lt _null_ _null_ _null_ )
+insert ( 1165 interval_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_le _null_ _null_ _null_ )
+insert ( 1166 interval_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_ge _null_ _null_ _null_ )
+insert ( 1167 interval_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_gt _null_ _null_ _null_ )
+insert ( 1168 interval_um 11 10 12 1 0 0 0 f f f t f i s 1 0 1186 1186 _null_ _null_ _null_ _null_ _null_ interval_um _null_ _null_ _null_ )
+insert ( 1169 interval_pl 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_pl _null_ _null_ _null_ )
+insert ( 1170 interval_mi 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_mi _null_ _null_ _null_ )
+insert ( 1171 date_part 11 10 12 1 0 0 0 f f f t f s s 2 0 701 "25 1184" _null_ _null_ _null_ _null_ _null_ timestamptz_part _null_ _null_ _null_ )
+insert ( 1172 date_part 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "25 1186" _null_ _null_ _null_ _null_ _null_ interval_part _null_ _null_ _null_ )
+insert ( 1174 timestamptz 11 10 12 1 0 0 0 f f f t f s s 1 0 1184 1082 _null_ _null_ _null_ _null_ _null_ date_timestamptz _null_ _null_ _null_ )
+insert ( 2711 justify_interval 11 10 12 1 0 0 0 f f f t f i s 1 0 1186 1186 _null_ _null_ _null_ _null_ _null_ interval_justify_interval _null_ _null_ _null_ )
+insert ( 1175 justify_hours 11 10 12 1 0 0 0 f f f t f i s 1 0 1186 1186 _null_ _null_ _null_ _null_ _null_ interval_justify_hours _null_ _null_ _null_ )
+insert ( 1295 justify_days 11 10 12 1 0 0 0 f f f t f i s 1 0 1186 1186 _null_ _null_ _null_ _null_ _null_ interval_justify_days _null_ _null_ _null_ )
+insert ( 1176 timestamptz 11 10 14 1 0 0 0 f f f t f s s 2 0 1184 "1082 1083" _null_ _null_ _null_ _null_ _null_ "select cast(($1 + $2) as timestamp with time zone)" _null_ _null_ _null_ )
+insert ( 1178 date 11 10 12 1 0 0 0 f f f t f s s 1 0 1082 1184 _null_ _null_ _null_ _null_ _null_ timestamptz_date _null_ _null_ _null_ )
+insert ( 1181 age 11 10 12 1 0 0 0 f f f t f s r 1 0 23 28 _null_ _null_ _null_ _null_ _null_ xid_age _null_ _null_ _null_ )
+insert ( 3939 mxid_age 11 10 12 1 0 0 0 f f f t f s s 1 0 23 28 _null_ _null_ _null_ _null_ _null_ mxid_age _null_ _null_ _null_ )
+insert ( 1188 timestamptz_mi 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_mi _null_ _null_ _null_ )
+insert ( 1189 timestamptz_pl_interval 11 10 12 1 0 0 0 f f f t f s s 2 0 1184 "1184 1186" _null_ _null_ _null_ _null_ _null_ timestamptz_pl_interval _null_ _null_ _null_ )
+insert ( 1190 timestamptz_mi_interval 11 10 12 1 0 0 0 f f f t f s s 2 0 1184 "1184 1186" _null_ _null_ _null_ _null_ _null_ timestamptz_mi_interval _null_ _null_ _null_ )
+insert ( 1195 timestamptz_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 1184 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_smaller _null_ _null_ _null_ )
+insert ( 1196 timestamptz_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 1184 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_larger _null_ _null_ _null_ )
+insert ( 1197 interval_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_smaller _null_ _null_ _null_ )
+insert ( 1198 interval_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_larger _null_ _null_ _null_ )
+insert ( 1199 age 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamptz_age _null_ _null_ _null_ )
+insert ( 3918 interval_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ interval_support _null_ _null_ _null_ )
+insert ( 1200 interval 11 10 12 1 0 0 3918 f f f t f i s 2 0 1186 "1186 23" _null_ _null_ _null_ _null_ _null_ interval_scale _null_ _null_ _null_ )
+insert ( 1215 obj_description 11 10 14 100 0 0 0 f f f t f s s 2 0 25 "26 19" _null_ _null_ _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = 11) and objsubid = 0" _null_ _null_ _null_ )
+insert ( 1216 col_description 11 10 14 100 0 0 0 f f f t f s s 2 0 25 "26 23" _null_ _null_ _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = ''pg_catalog.pg_class''::pg_catalog.regclass and objsubid = $2" _null_ _null_ _null_ )
+insert ( 1993 shobj_description 11 10 14 100 0 0 0 f f f t f s s 2 0 25 "26 19" _null_ _null_ _null_ _null_ _null_ "select description from pg_catalog.pg_shdescription where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = 11)" _null_ _null_ _null_ )
+insert ( 1217 date_trunc 11 10 12 1 0 0 0 f f f t f s s 2 0 1184 "25 1184" _null_ _null_ _null_ _null_ _null_ timestamptz_trunc _null_ _null_ _null_ )
+insert ( 1284 date_trunc 11 10 12 1 0 0 0 f f f t f s s 3 0 1184 "25 1184 25" _null_ _null_ _null_ _null_ _null_ timestamptz_trunc_zone _null_ _null_ _null_ )
+insert ( 1218 date_trunc 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "25 1186" _null_ _null_ _null_ _null_ _null_ interval_trunc _null_ _null_ _null_ )
+insert ( 1219 int8inc 11 10 12 1 0 0 0 f f f t f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ int8inc _null_ _null_ _null_ )
+insert ( 3546 int8dec 11 10 12 1 0 0 0 f f f t f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ int8dec _null_ _null_ _null_ )
+insert ( 2804 int8inc_any 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 2276" _null_ _null_ _null_ _null_ _null_ int8inc_any _null_ _null_ _null_ )
+insert ( 3547 int8dec_any 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 2276" _null_ _null_ _null_ _null_ _null_ int8dec_any _null_ _null_ _null_ )
+insert ( 1230 int8abs 11 10 12 1 0 0 0 f f f t f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ int8abs _null_ _null_ _null_ )
+insert ( 1236 int8larger 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8larger _null_ _null_ _null_ )
+insert ( 1237 int8smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8smaller _null_ _null_ _null_ )
+insert ( 1238 texticregexeq 11 10 12 1 0 0 1024 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ texticregexeq _null_ _null_ _null_ )
+insert ( 1024 texticregexeq_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ texticregexeq_support _null_ _null_ _null_ )
+insert ( 1239 texticregexne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ texticregexne _null_ _null_ _null_ )
+insert ( 1240 nameicregexeq 11 10 12 1 0 0 1024 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ nameicregexeq _null_ _null_ _null_ )
+insert ( 1241 nameicregexne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ nameicregexne _null_ _null_ _null_ )
+insert ( 1251 int4abs 11 10 12 1 0 0 0 f f f t f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ int4abs _null_ _null_ _null_ )
+insert ( 1253 int2abs 11 10 12 1 0 0 0 f f f t f i s 1 0 21 21 _null_ _null_ _null_ _null_ _null_ int2abs _null_ _null_ _null_ )
+insert ( 1271 overlaps 11 10 12 1 0 0 0 f f f f f i s 4 0 16 "1266 1266 1266 1266" _null_ _null_ _null_ _null_ _null_ overlaps_timetz _null_ _null_ _null_ )
+insert ( 1272 datetime_pl 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "1082 1083" _null_ _null_ _null_ _null_ _null_ datetime_timestamp _null_ _null_ _null_ )
+insert ( 1273 date_part 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "25 1266" _null_ _null_ _null_ _null_ _null_ timetz_part _null_ _null_ _null_ )
+insert ( 1274 int84pl 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 23" _null_ _null_ _null_ _null_ _null_ int84pl _null_ _null_ _null_ )
+insert ( 1275 int84mi 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 23" _null_ _null_ _null_ _null_ _null_ int84mi _null_ _null_ _null_ )
+insert ( 1276 int84mul 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 23" _null_ _null_ _null_ _null_ _null_ int84mul _null_ _null_ _null_ )
+insert ( 1277 int84div 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 23" _null_ _null_ _null_ _null_ _null_ int84div _null_ _null_ _null_ )
+insert ( 1278 int48pl 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "23 20" _null_ _null_ _null_ _null_ _null_ int48pl _null_ _null_ _null_ )
+insert ( 1279 int48mi 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "23 20" _null_ _null_ _null_ _null_ _null_ int48mi _null_ _null_ _null_ )
+insert ( 1280 int48mul 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "23 20" _null_ _null_ _null_ _null_ _null_ int48mul _null_ _null_ _null_ )
+insert ( 1281 int48div 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "23 20" _null_ _null_ _null_ _null_ _null_ int48div _null_ _null_ _null_ )
+insert ( 837 int82pl 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 21" _null_ _null_ _null_ _null_ _null_ int82pl _null_ _null_ _null_ )
+insert ( 838 int82mi 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 21" _null_ _null_ _null_ _null_ _null_ int82mi _null_ _null_ _null_ )
+insert ( 839 int82mul 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 21" _null_ _null_ _null_ _null_ _null_ int82mul _null_ _null_ _null_ )
+insert ( 840 int82div 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 21" _null_ _null_ _null_ _null_ _null_ int82div _null_ _null_ _null_ )
+insert ( 841 int28pl 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "21 20" _null_ _null_ _null_ _null_ _null_ int28pl _null_ _null_ _null_ )
+insert ( 942 int28mi 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "21 20" _null_ _null_ _null_ _null_ _null_ int28mi _null_ _null_ _null_ )
+insert ( 943 int28mul 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "21 20" _null_ _null_ _null_ _null_ _null_ int28mul _null_ _null_ _null_ )
+insert ( 948 int28div 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "21 20" _null_ _null_ _null_ _null_ _null_ int28div _null_ _null_ _null_ )
+insert ( 1287 oid 11 10 12 1 0 0 0 f f f t f i s 1 0 26 20 _null_ _null_ _null_ _null_ _null_ i8tooid _null_ _null_ _null_ )
+insert ( 1288 int8 11 10 12 1 0 0 0 f f f t f i s 1 0 20 26 _null_ _null_ _null_ _null_ _null_ oidtoi8 _null_ _null_ _null_ )
+insert ( 1291 suppress_redundant_updates_trigger 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ suppress_redundant_updates_trigger _null_ _null_ _null_ )
+insert ( 1292 tideq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "27 27" _null_ _null_ _null_ _null_ _null_ tideq _null_ _null_ _null_ )
+insert ( 1293 currtid 11 10 12 1 0 0 0 f f f t f v u 2 0 27 "26 27" _null_ _null_ _null_ _null_ _null_ currtid_byreloid _null_ _null_ _null_ )
+insert ( 1294 currtid2 11 10 12 1 0 0 0 f f f t f v u 2 0 27 "25 27" _null_ _null_ _null_ _null_ _null_ currtid_byrelname _null_ _null_ _null_ )
+insert ( 1265 tidne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "27 27" _null_ _null_ _null_ _null_ _null_ tidne _null_ _null_ _null_ )
+insert ( 2790 tidgt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "27 27" _null_ _null_ _null_ _null_ _null_ tidgt _null_ _null_ _null_ )
+insert ( 2791 tidlt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "27 27" _null_ _null_ _null_ _null_ _null_ tidlt _null_ _null_ _null_ )
+insert ( 2792 tidge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "27 27" _null_ _null_ _null_ _null_ _null_ tidge _null_ _null_ _null_ )
+insert ( 2793 tidle 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "27 27" _null_ _null_ _null_ _null_ _null_ tidle _null_ _null_ _null_ )
+insert ( 2794 bttidcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "27 27" _null_ _null_ _null_ _null_ _null_ bttidcmp _null_ _null_ _null_ )
+insert ( 2795 tidlarger 11 10 12 1 0 0 0 f f f t f i s 2 0 27 "27 27" _null_ _null_ _null_ _null_ _null_ tidlarger _null_ _null_ _null_ )
+insert ( 2796 tidsmaller 11 10 12 1 0 0 0 f f f t f i s 2 0 27 "27 27" _null_ _null_ _null_ _null_ _null_ tidsmaller _null_ _null_ _null_ )
+insert ( 2233 hashtid 11 10 12 1 0 0 0 f f f t f i s 1 0 23 27 _null_ _null_ _null_ _null_ _null_ hashtid _null_ _null_ _null_ )
+insert ( 2234 hashtidextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "27 20" _null_ _null_ _null_ _null_ _null_ hashtidextended _null_ _null_ _null_ )
+insert ( 1296 timedate_pl 11 10 14 1 0 0 0 f f f t f i s 2 0 1114 "1083 1082" _null_ _null_ _null_ _null_ _null_ "select ($2 + $1)" _null_ _null_ _null_ )
+insert ( 1297 datetimetz_pl 11 10 12 1 0 0 0 f f f t f i s 2 0 1184 "1082 1266" _null_ _null_ _null_ _null_ _null_ datetimetz_timestamptz _null_ _null_ _null_ )
+insert ( 1298 timetzdate_pl 11 10 14 1 0 0 0 f f f t f i s 2 0 1184 "1266 1082" _null_ _null_ _null_ _null_ _null_ "select ($2 + $1)" _null_ _null_ _null_ )
+insert ( 1299 now 11 10 12 1 0 0 0 f f f t f s s 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ now _null_ _null_ _null_ )
+insert ( 2647 transaction_timestamp 11 10 12 1 0 0 0 f f f t f s s 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ now _null_ _null_ _null_ )
+insert ( 2648 statement_timestamp 11 10 12 1 0 0 0 f f f t f s s 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ statement_timestamp _null_ _null_ _null_ )
+insert ( 2649 clock_timestamp 11 10 12 1 0 0 0 f f f t f v s 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ clock_timestamp _null_ _null_ _null_ )
+insert ( 1300 positionsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ positionsel _null_ _null_ _null_ )
+insert ( 1301 positionjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ positionjoinsel _null_ _null_ _null_ )
+insert ( 1302 contsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ contsel _null_ _null_ _null_ )
+insert ( 1303 contjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ contjoinsel _null_ _null_ _null_ )
+insert ( 1304 overlaps 11 10 12 1 0 0 0 f f f f f i s 4 0 16 "1184 1184 1184 1184" _null_ _null_ _null_ _null_ _null_ overlaps_timestamp _null_ _null_ _null_ )
+insert ( 1305 overlaps 11 10 14 1 0 0 0 f f f f f s s 4 0 16 "1184 1186 1184 1186" _null_ _null_ _null_ _null_ _null_ "select ($1, ($1 + $2)) overlaps ($3, ($3 + $4))" _null_ _null_ _null_ )
+insert ( 1306 overlaps 11 10 14 1 0 0 0 f f f f f s s 4 0 16 "1184 1184 1184 1186" _null_ _null_ _null_ _null_ _null_ "select ($1, $2) overlaps ($3, ($3 + $4))" _null_ _null_ _null_ )
+insert ( 1307 overlaps 11 10 14 1 0 0 0 f f f f f s s 4 0 16 "1184 1186 1184 1184" _null_ _null_ _null_ _null_ _null_ "select ($1, ($1 + $2)) overlaps ($3, $4)" _null_ _null_ _null_ )
+insert ( 1308 overlaps 11 10 12 1 0 0 0 f f f f f i s 4 0 16 "1083 1083 1083 1083" _null_ _null_ _null_ _null_ _null_ overlaps_time _null_ _null_ _null_ )
+insert ( 1309 overlaps 11 10 14 1 0 0 0 f f f f f i s 4 0 16 "1083 1186 1083 1186" _null_ _null_ _null_ _null_ _null_ "select ($1, ($1 + $2)) overlaps ($3, ($3 + $4))" _null_ _null_ _null_ )
+insert ( 1310 overlaps 11 10 14 1 0 0 0 f f f f f i s 4 0 16 "1083 1083 1083 1186" _null_ _null_ _null_ _null_ _null_ "select ($1, $2) overlaps ($3, ($3 + $4))" _null_ _null_ _null_ )
+insert ( 1311 overlaps 11 10 14 1 0 0 0 f f f f f i s 4 0 16 "1083 1186 1083 1083" _null_ _null_ _null_ _null_ _null_ "select ($1, ($1 + $2)) overlaps ($3, $4)" _null_ _null_ _null_ )
+insert ( 1312 timestamp_in 11 10 12 1 0 0 0 f f f t f s s 3 0 1114 "2275 26 23" _null_ _null_ _null_ _null_ _null_ timestamp_in _null_ _null_ _null_ )
+insert ( 1313 timestamp_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 1114 _null_ _null_ _null_ _null_ _null_ timestamp_out _null_ _null_ _null_ )
+insert ( 2905 timestamptypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ timestamptypmodin _null_ _null_ _null_ )
+insert ( 2906 timestamptypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ timestamptypmodout _null_ _null_ _null_ )
+insert ( 1314 timestamptz_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1184 1184" _null_ _null_ _null_ _null_ _null_ timestamp_cmp _null_ _null_ _null_ )
+insert ( 1315 interval_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1186 1186" _null_ _null_ _null_ _null_ _null_ interval_cmp _null_ _null_ _null_ )
+insert ( 1316 time 11 10 12 1 0 0 0 f f f t f i s 1 0 1083 1114 _null_ _null_ _null_ _null_ _null_ timestamp_time _null_ _null_ _null_ )
+insert ( 1317 length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 25 _null_ _null_ _null_ _null_ _null_ textlen _null_ _null_ _null_ )
+insert ( 1318 length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1042 _null_ _null_ _null_ _null_ _null_ bpcharlen _null_ _null_ _null_ )
+insert ( 1319 xideqint4 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "28 23" _null_ _null_ _null_ _null_ _null_ xideq _null_ _null_ _null_ )
+insert ( 3309 xidneqint4 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "28 23" _null_ _null_ _null_ _null_ _null_ xidneq _null_ _null_ _null_ )
+insert ( 1326 interval_div 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1186 701" _null_ _null_ _null_ _null_ _null_ interval_div _null_ _null_ _null_ )
+insert ( 1339 dlog10 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dlog10 _null_ _null_ _null_ )
+insert ( 1340 log 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dlog10 _null_ _null_ _null_ )
+insert ( 1194 log10 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dlog10 _null_ _null_ _null_ )
+insert ( 1341 ln 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dlog1 _null_ _null_ _null_ )
+insert ( 1342 round 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dround _null_ _null_ _null_ )
+insert ( 1343 trunc 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dtrunc _null_ _null_ _null_ )
+insert ( 1344 sqrt 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dsqrt _null_ _null_ _null_ )
+insert ( 1345 cbrt 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dcbrt _null_ _null_ _null_ )
+insert ( 1346 pow 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ dpow _null_ _null_ _null_ )
+insert ( 1368 power 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ dpow _null_ _null_ _null_ )
+insert ( 1347 exp 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dexp _null_ _null_ _null_ )
+insert ( 1348 obj_description 11 10 14 100 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and objsubid = 0" _null_ _null_ _null_ )
+insert ( 1349 oidvectortypes 11 10 12 1 0 0 0 f f f t f s s 1 0 25 30 _null_ _null_ _null_ _null_ _null_ oidvectortypes _null_ _null_ _null_ )
+insert ( 1350 timetz_in 11 10 12 1 0 0 0 f f f t f s s 3 0 1266 "2275 26 23" _null_ _null_ _null_ _null_ _null_ timetz_in _null_ _null_ _null_ )
+insert ( 1351 timetz_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 1266 _null_ _null_ _null_ _null_ _null_ timetz_out _null_ _null_ _null_ )
+insert ( 2911 timetztypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ timetztypmodin _null_ _null_ _null_ )
+insert ( 2912 timetztypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ timetztypmodout _null_ _null_ _null_ )
+insert ( 1352 timetz_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1266 1266" _null_ _null_ _null_ _null_ _null_ timetz_eq _null_ _null_ _null_ )
+insert ( 1353 timetz_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1266 1266" _null_ _null_ _null_ _null_ _null_ timetz_ne _null_ _null_ _null_ )
+insert ( 1354 timetz_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1266 1266" _null_ _null_ _null_ _null_ _null_ timetz_lt _null_ _null_ _null_ )
+insert ( 1355 timetz_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1266 1266" _null_ _null_ _null_ _null_ _null_ timetz_le _null_ _null_ _null_ )
+insert ( 1356 timetz_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1266 1266" _null_ _null_ _null_ _null_ _null_ timetz_ge _null_ _null_ _null_ )
+insert ( 1357 timetz_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1266 1266" _null_ _null_ _null_ _null_ _null_ timetz_gt _null_ _null_ _null_ )
+insert ( 1358 timetz_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1266 1266" _null_ _null_ _null_ _null_ _null_ timetz_cmp _null_ _null_ _null_ )
+insert ( 1359 timestamptz 11 10 12 1 0 0 0 f f f t f i s 2 0 1184 "1082 1266" _null_ _null_ _null_ _null_ _null_ datetimetz_timestamptz _null_ _null_ _null_ )
+insert ( 1367 character_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1042 _null_ _null_ _null_ _null_ _null_ bpcharlen _null_ _null_ _null_ )
+insert ( 1369 character_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 25 _null_ _null_ _null_ _null_ _null_ textlen _null_ _null_ _null_ )
+insert ( 1370 interval 11 10 12 1 0 0 0 f f f t f i s 1 0 1186 1083 _null_ _null_ _null_ _null_ _null_ time_interval _null_ _null_ _null_ )
+insert ( 1372 char_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1042 _null_ _null_ _null_ _null_ _null_ bpcharlen _null_ _null_ _null_ )
+insert ( 1374 octet_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 25 _null_ _null_ _null_ _null_ _null_ textoctetlen _null_ _null_ _null_ )
+insert ( 1375 octet_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1042 _null_ _null_ _null_ _null_ _null_ bpcharoctetlen _null_ _null_ _null_ )
+insert ( 1377 time_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 1083 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_larger _null_ _null_ _null_ )
+insert ( 1378 time_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 1083 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_smaller _null_ _null_ _null_ )
+insert ( 1379 timetz_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 1266 "1266 1266" _null_ _null_ _null_ _null_ _null_ timetz_larger _null_ _null_ _null_ )
+insert ( 1380 timetz_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 1266 "1266 1266" _null_ _null_ _null_ _null_ _null_ timetz_smaller _null_ _null_ _null_ )
+insert ( 1381 char_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 25 _null_ _null_ _null_ _null_ _null_ textlen _null_ _null_ _null_ )
+insert ( 1384 date_part 11 10 14 1 0 0 0 f f f t f i s 2 0 701 "25 1082" _null_ _null_ _null_ _null_ _null_ "select pg_catalog.date_part($1, cast($2 as timestamp without time zone))" _null_ _null_ _null_ )
+insert ( 1385 date_part 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "25 1083" _null_ _null_ _null_ _null_ _null_ time_part _null_ _null_ _null_ )
+insert ( 1386 age 11 10 14 1 0 0 0 f f f t f s s 1 0 1186 1184 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.age(cast(current_date as timestamp with time zone), $1)" _null_ _null_ _null_ )
+insert ( 1388 timetz 11 10 12 1 0 0 0 f f f t f s s 1 0 1266 1184 _null_ _null_ _null_ _null_ _null_ timestamptz_timetz _null_ _null_ _null_ )
+insert ( 1373 isfinite 11 10 12 1 0 0 0 f f f t f i s 1 0 16 1082 _null_ _null_ _null_ _null_ _null_ date_finite _null_ _null_ _null_ )
+insert ( 1389 isfinite 11 10 12 1 0 0 0 f f f t f i s 1 0 16 1184 _null_ _null_ _null_ _null_ _null_ timestamp_finite _null_ _null_ _null_ )
+insert ( 1390 isfinite 11 10 12 1 0 0 0 f f f t f i s 1 0 16 1186 _null_ _null_ _null_ _null_ _null_ interval_finite _null_ _null_ _null_ )
+insert ( 1376 factorial 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ numeric_fac _null_ _null_ _null_ )
+insert ( 1394 abs 11 10 12 1 0 0 0 f f f t f i s 1 0 700 700 _null_ _null_ _null_ _null_ _null_ float4abs _null_ _null_ _null_ )
+insert ( 1395 abs 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ float8abs _null_ _null_ _null_ )
+insert ( 1396 abs 11 10 12 1 0 0 0 f f f t f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ int8abs _null_ _null_ _null_ )
+insert ( 1397 abs 11 10 12 1 0 0 0 f f f t f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ int4abs _null_ _null_ _null_ )
+insert ( 1398 abs 11 10 12 1 0 0 0 f f f t f i s 1 0 21 21 _null_ _null_ _null_ _null_ _null_ int2abs _null_ _null_ _null_ )
+insert ( 1400 name 11 10 12 1 0 0 0 f f f t f i s 1 0 19 1043 _null_ _null_ _null_ _null_ _null_ text_name _null_ _null_ _null_ )
+insert ( 1401 varchar 11 10 12 1 0 0 0 f f f t f i s 1 0 1043 19 _null_ _null_ _null_ _null_ _null_ name_text _null_ _null_ _null_ )
+insert ( 1402 current_schema 11 10 12 1 0 0 0 f f f t f s u 0 0 19 "" _null_ _null_ _null_ _null_ _null_ current_schema _null_ _null_ _null_ )
+insert ( 1403 current_schemas 11 10 12 1 0 0 0 f f f t f s u 1 0 1003 16 _null_ _null_ _null_ _null_ _null_ current_schemas _null_ _null_ _null_ )
+insert ( 1404 overlay 11 10 12 1 0 0 0 f f f t f i s 4 0 25 "25 25 23 23" _null_ _null_ _null_ _null_ _null_ textoverlay _null_ _null_ _null_ )
+insert ( 1405 overlay 11 10 12 1 0 0 0 f f f t f i s 3 0 25 "25 25 23" _null_ _null_ _null_ _null_ _null_ textoverlay_no_len _null_ _null_ _null_ )
+insert ( 1406 isvertical 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_vert _null_ _null_ _null_ )
+insert ( 1407 ishorizontal 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 600" _null_ _null_ _null_ _null_ _null_ point_horiz _null_ _null_ _null_ )
+insert ( 1408 isparallel 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_parallel _null_ _null_ _null_ )
+insert ( 1409 isperp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_perp _null_ _null_ _null_ )
+insert ( 1410 isvertical 11 10 12 1 0 0 0 f f f t f i s 1 0 16 601 _null_ _null_ _null_ _null_ _null_ lseg_vertical _null_ _null_ _null_ )
+insert ( 1411 ishorizontal 11 10 12 1 0 0 0 f f f t f i s 1 0 16 601 _null_ _null_ _null_ _null_ _null_ lseg_horizontal _null_ _null_ _null_ )
+insert ( 1412 isparallel 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "628 628" _null_ _null_ _null_ _null_ _null_ line_parallel _null_ _null_ _null_ )
+insert ( 1413 isperp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "628 628" _null_ _null_ _null_ _null_ _null_ line_perp _null_ _null_ _null_ )
+insert ( 1414 isvertical 11 10 12 1 0 0 0 f f f t f i s 1 0 16 628 _null_ _null_ _null_ _null_ _null_ line_vertical _null_ _null_ _null_ )
+insert ( 1415 ishorizontal 11 10 12 1 0 0 0 f f f t f i s 1 0 16 628 _null_ _null_ _null_ _null_ _null_ line_horizontal _null_ _null_ _null_ )
+insert ( 1416 point 11 10 12 1 0 0 0 f f f t f i s 1 0 600 718 _null_ _null_ _null_ _null_ _null_ circle_center _null_ _null_ _null_ )
+insert ( 1419 time 11 10 12 1 0 0 0 f f f t f i s 1 0 1083 1186 _null_ _null_ _null_ _null_ _null_ interval_time _null_ _null_ _null_ )
+insert ( 1421 box 11 10 12 1 0 0 0 f f f t f i s 2 0 603 "600 600" _null_ _null_ _null_ _null_ _null_ points_box _null_ _null_ _null_ )
+insert ( 1422 box_add 11 10 12 1 0 0 0 f f f t f i s 2 0 603 "603 600" _null_ _null_ _null_ _null_ _null_ box_add _null_ _null_ _null_ )
+insert ( 1423 box_sub 11 10 12 1 0 0 0 f f f t f i s 2 0 603 "603 600" _null_ _null_ _null_ _null_ _null_ box_sub _null_ _null_ _null_ )
+insert ( 1424 box_mul 11 10 12 1 0 0 0 f f f t f i s 2 0 603 "603 600" _null_ _null_ _null_ _null_ _null_ box_mul _null_ _null_ _null_ )
+insert ( 1425 box_div 11 10 12 1 0 0 0 f f f t f i s 2 0 603 "603 600" _null_ _null_ _null_ _null_ _null_ box_div _null_ _null_ _null_ )
+insert ( 1426 path_contain_pt 11 10 14 1 0 0 0 f f f t f i s 2 0 16 "602 600" _null_ _null_ _null_ _null_ _null_ "select pg_catalog.on_ppath($2, $1)" _null_ _null_ _null_ )
+insert ( 1428 poly_contain_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 600" _null_ _null_ _null_ _null_ _null_ poly_contain_pt _null_ _null_ _null_ )
+insert ( 1429 pt_contained_poly 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 604" _null_ _null_ _null_ _null_ _null_ pt_contained_poly _null_ _null_ _null_ )
+insert ( 1430 isclosed 11 10 12 1 0 0 0 f f f t f i s 1 0 16 602 _null_ _null_ _null_ _null_ _null_ path_isclosed _null_ _null_ _null_ )
+insert ( 1431 isopen 11 10 12 1 0 0 0 f f f t f i s 1 0 16 602 _null_ _null_ _null_ _null_ _null_ path_isopen _null_ _null_ _null_ )
+insert ( 1432 path_npoints 11 10 12 1 0 0 0 f f f t f i s 1 0 23 602 _null_ _null_ _null_ _null_ _null_ path_npoints _null_ _null_ _null_ )
+insert ( 1433 pclose 11 10 12 1 0 0 0 f f f t f i s 1 0 602 602 _null_ _null_ _null_ _null_ _null_ path_close _null_ _null_ _null_ )
+insert ( 1434 popen 11 10 12 1 0 0 0 f f f t f i s 1 0 602 602 _null_ _null_ _null_ _null_ _null_ path_open _null_ _null_ _null_ )
+insert ( 1435 path_add 11 10 12 1 0 0 0 f f f t f i s 2 0 602 "602 602" _null_ _null_ _null_ _null_ _null_ path_add _null_ _null_ _null_ )
+insert ( 1436 path_add_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 602 "602 600" _null_ _null_ _null_ _null_ _null_ path_add_pt _null_ _null_ _null_ )
+insert ( 1437 path_sub_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 602 "602 600" _null_ _null_ _null_ _null_ _null_ path_sub_pt _null_ _null_ _null_ )
+insert ( 1438 path_mul_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 602 "602 600" _null_ _null_ _null_ _null_ _null_ path_mul_pt _null_ _null_ _null_ )
+insert ( 1439 path_div_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 602 "602 600" _null_ _null_ _null_ _null_ _null_ path_div_pt _null_ _null_ _null_ )
+insert ( 1440 point 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "701 701" _null_ _null_ _null_ _null_ _null_ construct_point _null_ _null_ _null_ )
+insert ( 1441 point_add 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "600 600" _null_ _null_ _null_ _null_ _null_ point_add _null_ _null_ _null_ )
+insert ( 1442 point_sub 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "600 600" _null_ _null_ _null_ _null_ _null_ point_sub _null_ _null_ _null_ )
+insert ( 1443 point_mul 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "600 600" _null_ _null_ _null_ _null_ _null_ point_mul _null_ _null_ _null_ )
+insert ( 1444 point_div 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "600 600" _null_ _null_ _null_ _null_ _null_ point_div _null_ _null_ _null_ )
+insert ( 1445 poly_npoints 11 10 12 1 0 0 0 f f f t f i s 1 0 23 604 _null_ _null_ _null_ _null_ _null_ poly_npoints _null_ _null_ _null_ )
+insert ( 1446 box 11 10 12 1 0 0 0 f f f t f i s 1 0 603 604 _null_ _null_ _null_ _null_ _null_ poly_box _null_ _null_ _null_ )
+insert ( 1447 path 11 10 12 1 0 0 0 f f f t f i s 1 0 602 604 _null_ _null_ _null_ _null_ _null_ poly_path _null_ _null_ _null_ )
+insert ( 1448 polygon 11 10 12 1 0 0 0 f f f t f i s 1 0 604 603 _null_ _null_ _null_ _null_ _null_ box_poly _null_ _null_ _null_ )
+insert ( 1449 polygon 11 10 12 1 0 0 0 f f f t f i s 1 0 604 602 _null_ _null_ _null_ _null_ _null_ path_poly _null_ _null_ _null_ )
+insert ( 1450 circle_in 11 10 12 1 0 0 0 f f f t f i s 1 0 718 2275 _null_ _null_ _null_ _null_ _null_ circle_in _null_ _null_ _null_ )
+insert ( 1451 circle_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 718 _null_ _null_ _null_ _null_ _null_ circle_out _null_ _null_ _null_ )
+insert ( 1452 circle_same 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_same _null_ _null_ _null_ )
+insert ( 1453 circle_contain 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_contain _null_ _null_ _null_ )
+insert ( 1454 circle_left 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_left _null_ _null_ _null_ )
+insert ( 1455 circle_overleft 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_overleft _null_ _null_ _null_ )
+insert ( 1456 circle_overright 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_overright _null_ _null_ _null_ )
+insert ( 1457 circle_right 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_right _null_ _null_ _null_ )
+insert ( 1458 circle_contained 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_contained _null_ _null_ _null_ )
+insert ( 1459 circle_overlap 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_overlap _null_ _null_ _null_ )
+insert ( 1460 circle_below 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_below _null_ _null_ _null_ )
+insert ( 1461 circle_above 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_above _null_ _null_ _null_ )
+insert ( 1462 circle_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_eq _null_ _null_ _null_ )
+insert ( 1463 circle_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_ne _null_ _null_ _null_ )
+insert ( 1464 circle_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_lt _null_ _null_ _null_ )
+insert ( 1465 circle_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_gt _null_ _null_ _null_ )
+insert ( 1466 circle_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_le _null_ _null_ _null_ )
+insert ( 1467 circle_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_ge _null_ _null_ _null_ )
+insert ( 1468 area 11 10 12 1 0 0 0 f f f t f i s 1 0 701 718 _null_ _null_ _null_ _null_ _null_ circle_area _null_ _null_ _null_ )
+insert ( 1469 diameter 11 10 12 1 0 0 0 f f f t f i s 1 0 701 718 _null_ _null_ _null_ _null_ _null_ circle_diameter _null_ _null_ _null_ )
+insert ( 1470 radius 11 10 12 1 0 0 0 f f f t f i s 1 0 701 718 _null_ _null_ _null_ _null_ _null_ circle_radius _null_ _null_ _null_ )
+insert ( 1471 circle_distance 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "718 718" _null_ _null_ _null_ _null_ _null_ circle_distance _null_ _null_ _null_ )
+insert ( 1472 circle_center 11 10 12 1 0 0 0 f f f t f i s 1 0 600 718 _null_ _null_ _null_ _null_ _null_ circle_center _null_ _null_ _null_ )
+insert ( 1473 circle 11 10 12 1 0 0 0 f f f t f i s 2 0 718 "600 701" _null_ _null_ _null_ _null_ _null_ cr_circle _null_ _null_ _null_ )
+insert ( 1474 circle 11 10 12 1 0 0 0 f f f t f i s 1 0 718 604 _null_ _null_ _null_ _null_ _null_ poly_circle _null_ _null_ _null_ )
+insert ( 1475 polygon 11 10 12 1 0 0 0 f f f t f i s 2 0 604 "23 718" _null_ _null_ _null_ _null_ _null_ circle_poly _null_ _null_ _null_ )
+insert ( 1476 dist_pc 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "600 718" _null_ _null_ _null_ _null_ _null_ dist_pc _null_ _null_ _null_ )
+insert ( 1477 circle_contain_pt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 600" _null_ _null_ _null_ _null_ _null_ circle_contain_pt _null_ _null_ _null_ )
+insert ( 1478 pt_contained_circle 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "600 718" _null_ _null_ _null_ _null_ _null_ pt_contained_circle _null_ _null_ _null_ )
+insert ( 4091 box 11 10 12 1 0 0 0 f f f t f i s 1 0 603 600 _null_ _null_ _null_ _null_ _null_ point_box _null_ _null_ _null_ )
+insert ( 1479 circle 11 10 12 1 0 0 0 f f f t f i s 1 0 718 603 _null_ _null_ _null_ _null_ _null_ box_circle _null_ _null_ _null_ )
+insert ( 1480 box 11 10 12 1 0 0 0 f f f t f i s 1 0 603 718 _null_ _null_ _null_ _null_ _null_ circle_box _null_ _null_ _null_ )
+insert ( 1482 lseg_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_ne _null_ _null_ _null_ )
+insert ( 1483 lseg_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_lt _null_ _null_ _null_ )
+insert ( 1484 lseg_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_le _null_ _null_ _null_ )
+insert ( 1485 lseg_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_gt _null_ _null_ _null_ )
+insert ( 1486 lseg_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "601 601" _null_ _null_ _null_ _null_ _null_ lseg_ge _null_ _null_ _null_ )
+insert ( 1487 lseg_length 11 10 12 1 0 0 0 f f f t f i s 1 0 701 601 _null_ _null_ _null_ _null_ _null_ lseg_length _null_ _null_ _null_ )
+insert ( 1488 close_ls 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "628 601" _null_ _null_ _null_ _null_ _null_ close_ls _null_ _null_ _null_ )
+insert ( 1489 close_lseg 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "601 601" _null_ _null_ _null_ _null_ _null_ close_lseg _null_ _null_ _null_ )
+insert ( 1490 line_in 11 10 12 1 0 0 0 f f f t f i s 1 0 628 2275 _null_ _null_ _null_ _null_ _null_ line_in _null_ _null_ _null_ )
+insert ( 1491 line_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 628 _null_ _null_ _null_ _null_ _null_ line_out _null_ _null_ _null_ )
+insert ( 1492 line_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "628 628" _null_ _null_ _null_ _null_ _null_ line_eq _null_ _null_ _null_ )
+insert ( 1493 line 11 10 12 1 0 0 0 f f f t f i s 2 0 628 "600 600" _null_ _null_ _null_ _null_ _null_ line_construct_pp _null_ _null_ _null_ )
+insert ( 1494 line_interpt 11 10 12 1 0 0 0 f f f t f i s 2 0 600 "628 628" _null_ _null_ _null_ _null_ _null_ line_interpt _null_ _null_ _null_ )
+insert ( 1495 line_intersect 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "628 628" _null_ _null_ _null_ _null_ _null_ line_intersect _null_ _null_ _null_ )
+insert ( 1496 line_parallel 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "628 628" _null_ _null_ _null_ _null_ _null_ line_parallel _null_ _null_ _null_ )
+insert ( 1497 line_perp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "628 628" _null_ _null_ _null_ _null_ _null_ line_perp _null_ _null_ _null_ )
+insert ( 1498 line_vertical 11 10 12 1 0 0 0 f f f t f i s 1 0 16 628 _null_ _null_ _null_ _null_ _null_ line_vertical _null_ _null_ _null_ )
+insert ( 1499 line_horizontal 11 10 12 1 0 0 0 f f f t f i s 1 0 16 628 _null_ _null_ _null_ _null_ _null_ line_horizontal _null_ _null_ _null_ )
+insert ( 1530 length 11 10 12 1 0 0 0 f f f t f i s 1 0 701 601 _null_ _null_ _null_ _null_ _null_ lseg_length _null_ _null_ _null_ )
+insert ( 1531 length 11 10 12 1 0 0 0 f f f t f i s 1 0 701 602 _null_ _null_ _null_ _null_ _null_ path_length _null_ _null_ _null_ )
+insert ( 1532 point 11 10 12 1 0 0 0 f f f t f i s 1 0 600 601 _null_ _null_ _null_ _null_ _null_ lseg_center _null_ _null_ _null_ )
+insert ( 1533 point 11 10 12 1 0 0 0 f f f t f i s 1 0 600 602 _null_ _null_ _null_ _null_ _null_ path_center _null_ _null_ _null_ )
+insert ( 1534 point 11 10 12 1 0 0 0 f f f t f i s 1 0 600 603 _null_ _null_ _null_ _null_ _null_ box_center _null_ _null_ _null_ )
+insert ( 1540 point 11 10 12 1 0 0 0 f f f t f i s 1 0 600 604 _null_ _null_ _null_ _null_ _null_ poly_center _null_ _null_ _null_ )
+insert ( 1541 lseg 11 10 12 1 0 0 0 f f f t f i s 1 0 601 603 _null_ _null_ _null_ _null_ _null_ box_diagonal _null_ _null_ _null_ )
+insert ( 1542 center 11 10 12 1 0 0 0 f f f t f i s 1 0 600 603 _null_ _null_ _null_ _null_ _null_ box_center _null_ _null_ _null_ )
+insert ( 1543 center 11 10 12 1 0 0 0 f f f t f i s 1 0 600 718 _null_ _null_ _null_ _null_ _null_ circle_center _null_ _null_ _null_ )
+insert ( 1544 polygon 11 10 14 1 0 0 0 f f f t f i s 1 0 604 718 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.polygon(12, $1)" _null_ _null_ _null_ )
+insert ( 1545 npoints 11 10 12 1 0 0 0 f f f t f i s 1 0 23 602 _null_ _null_ _null_ _null_ _null_ path_npoints _null_ _null_ _null_ )
+insert ( 1556 npoints 11 10 12 1 0 0 0 f f f t f i s 1 0 23 604 _null_ _null_ _null_ _null_ _null_ poly_npoints _null_ _null_ _null_ )
+insert ( 1564 bit_in 11 10 12 1 0 0 0 f f f t f i s 3 0 1560 "2275 26 23" _null_ _null_ _null_ _null_ _null_ bit_in _null_ _null_ _null_ )
+insert ( 1565 bit_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 1560 _null_ _null_ _null_ _null_ _null_ bit_out _null_ _null_ _null_ )
+insert ( 2919 bittypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ bittypmodin _null_ _null_ _null_ )
+insert ( 2920 bittypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ bittypmodout _null_ _null_ _null_ )
+insert ( 1569 like 11 10 12 1 0 0 1023 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ textlike _null_ _null_ _null_ )
+insert ( 1570 notlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ textnlike _null_ _null_ _null_ )
+insert ( 1571 like 11 10 12 1 0 0 1023 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ namelike _null_ _null_ _null_ )
+insert ( 1572 notlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ namenlike _null_ _null_ _null_ )
+insert ( 1574 nextval 11 10 12 1 0 0 0 f f f t f v u 1 0 20 2205 _null_ _null_ _null_ _null_ _null_ nextval_oid _null_ _null_ _null_ )
+insert ( 1575 currval 11 10 12 1 0 0 0 f f f t f v u 1 0 20 2205 _null_ _null_ _null_ _null_ _null_ currval_oid _null_ _null_ _null_ )
+insert ( 1576 setval 11 10 12 1 0 0 0 f f f t f v u 2 0 20 "2205 20" _null_ _null_ _null_ _null_ _null_ setval_oid _null_ _null_ _null_ )
+insert ( 1765 setval 11 10 12 1 0 0 0 f f f t f v u 3 0 20 "2205 20 16" _null_ _null_ _null_ _null_ _null_ setval3_oid _null_ _null_ _null_ )
+insert ( 3078 pg_sequence_parameters 11 10 12 1 0 0 0 f f f t f s s 1 0 2249 26 "{26,20,20,20,20,16,20,26}" "{i,o,o,o,o,o,o,o}" "{sequence_oid,start_value,minimum_value,maximum_value,increment,cycle_option,cache_size,data_type}" _null_ _null_ pg_sequence_parameters _null_ _null_ _null_ )
+insert ( 4032 pg_sequence_last_value 11 10 12 1 0 0 0 f f f t f v u 1 0 20 2205 _null_ _null_ _null_ _null_ _null_ pg_sequence_last_value _null_ _null_ _null_ )
+insert ( 275 pg_nextoid 11 10 12 1 0 0 0 f f f t f v u 3 0 26 "2205 19 2205" _null_ _null_ _null_ _null_ _null_ pg_nextoid _null_ _null_ _null_ )
+insert ( 1579 varbit_in 11 10 12 1 0 0 0 f f f t f i s 3 0 1562 "2275 26 23" _null_ _null_ _null_ _null_ _null_ varbit_in _null_ _null_ _null_ )
+insert ( 1580 varbit_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 1562 _null_ _null_ _null_ _null_ _null_ varbit_out _null_ _null_ _null_ )
+insert ( 2902 varbittypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ varbittypmodin _null_ _null_ _null_ )
+insert ( 2921 varbittypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ varbittypmodout _null_ _null_ _null_ )
+insert ( 1581 biteq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1560 1560" _null_ _null_ _null_ _null_ _null_ biteq _null_ _null_ _null_ )
+insert ( 1582 bitne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1560 1560" _null_ _null_ _null_ _null_ _null_ bitne _null_ _null_ _null_ )
+insert ( 1592 bitge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1560 1560" _null_ _null_ _null_ _null_ _null_ bitge _null_ _null_ _null_ )
+insert ( 1593 bitgt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1560 1560" _null_ _null_ _null_ _null_ _null_ bitgt _null_ _null_ _null_ )
+insert ( 1594 bitle 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1560 1560" _null_ _null_ _null_ _null_ _null_ bitle _null_ _null_ _null_ )
+insert ( 1595 bitlt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1560 1560" _null_ _null_ _null_ _null_ _null_ bitlt _null_ _null_ _null_ )
+insert ( 1596 bitcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1560 1560" _null_ _null_ _null_ _null_ _null_ bitcmp _null_ _null_ _null_ )
+insert ( 1598 random 11 10 12 1 0 0 0 f f f t f v r 0 0 701 "" _null_ _null_ _null_ _null_ _null_ drandom _null_ _null_ _null_ )
+insert ( 1599 setseed 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 701 _null_ _null_ _null_ _null_ _null_ setseed _null_ _null_ _null_ )
+insert ( 1600 asin 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dasin _null_ _null_ _null_ )
+insert ( 1601 acos 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dacos _null_ _null_ _null_ )
+insert ( 1602 atan 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ datan _null_ _null_ _null_ )
+insert ( 1603 atan2 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ datan2 _null_ _null_ _null_ )
+insert ( 1604 sin 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dsin _null_ _null_ _null_ )
+insert ( 1605 cos 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dcos _null_ _null_ _null_ )
+insert ( 1606 tan 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dtan _null_ _null_ _null_ )
+insert ( 1607 cot 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dcot _null_ _null_ _null_ )
+insert ( 2731 asind 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dasind _null_ _null_ _null_ )
+insert ( 2732 acosd 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dacosd _null_ _null_ _null_ )
+insert ( 2733 atand 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ datand _null_ _null_ _null_ )
+insert ( 2734 atan2d 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ datan2d _null_ _null_ _null_ )
+insert ( 2735 sind 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dsind _null_ _null_ _null_ )
+insert ( 2736 cosd 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dcosd _null_ _null_ _null_ )
+insert ( 2737 tand 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dtand _null_ _null_ _null_ )
+insert ( 2738 cotd 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dcotd _null_ _null_ _null_ )
+insert ( 1608 degrees 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ degrees _null_ _null_ _null_ )
+insert ( 1609 radians 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ radians _null_ _null_ _null_ )
+insert ( 1610 pi 11 10 12 1 0 0 0 f f f t f i s 0 0 701 "" _null_ _null_ _null_ _null_ _null_ dpi _null_ _null_ _null_ )
+insert ( 2462 sinh 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dsinh _null_ _null_ _null_ )
+insert ( 2463 cosh 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dcosh _null_ _null_ _null_ )
+insert ( 2464 tanh 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dtanh _null_ _null_ _null_ )
+insert ( 2465 asinh 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dasinh _null_ _null_ _null_ )
+insert ( 2466 acosh 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ dacosh _null_ _null_ _null_ )
+insert ( 2467 atanh 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ datanh _null_ _null_ _null_ )
+insert ( 1618 interval_mul 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1186 701" _null_ _null_ _null_ _null_ _null_ interval_mul _null_ _null_ _null_ )
+insert ( 1620 ascii 11 10 12 1 0 0 0 f f f t f i s 1 0 23 25 _null_ _null_ _null_ _null_ _null_ ascii _null_ _null_ _null_ )
+insert ( 1621 chr 11 10 12 1 0 0 0 f f f t f i s 1 0 25 23 _null_ _null_ _null_ _null_ _null_ chr _null_ _null_ _null_ )
+insert ( 1622 repeat 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 23" _null_ _null_ _null_ _null_ _null_ repeat _null_ _null_ _null_ )
+insert ( 1623 similar_escape 11 10 12 1 0 0 0 f f f f f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ similar_escape _null_ _null_ _null_ )
+insert ( 1986 similar_to_escape 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ similar_to_escape_2 _null_ _null_ _null_ )
+insert ( 1987 similar_to_escape 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ similar_to_escape_1 _null_ _null_ _null_ )
+insert ( 1624 mul_d_interval 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "701 1186" _null_ _null_ _null_ _null_ _null_ mul_d_interval _null_ _null_ _null_ )
+insert ( 1631 bpcharlike 11 10 12 1 0 0 1023 f f f t f i s 2 0 16 "1042 25" _null_ _null_ _null_ _null_ _null_ textlike _null_ _null_ _null_ )
+insert ( 1632 bpcharnlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1042 25" _null_ _null_ _null_ _null_ _null_ textnlike _null_ _null_ _null_ )
+insert ( 1633 texticlike 11 10 12 1 0 0 1025 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ texticlike _null_ _null_ _null_ )
+insert ( 1025 texticlike_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ texticlike_support _null_ _null_ _null_ )
+insert ( 1634 texticnlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ texticnlike _null_ _null_ _null_ )
+insert ( 1635 nameiclike 11 10 12 1 0 0 1025 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ nameiclike _null_ _null_ _null_ )
+insert ( 1636 nameicnlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ nameicnlike _null_ _null_ _null_ )
+insert ( 1637 like_escape 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ like_escape _null_ _null_ _null_ )
+insert ( 1656 bpcharicregexeq 11 10 12 1 0 0 1024 f f f t f i s 2 0 16 "1042 25" _null_ _null_ _null_ _null_ _null_ texticregexeq _null_ _null_ _null_ )
+insert ( 1657 bpcharicregexne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1042 25" _null_ _null_ _null_ _null_ _null_ texticregexne _null_ _null_ _null_ )
+insert ( 1658 bpcharregexeq 11 10 12 1 0 0 1364 f f f t f i s 2 0 16 "1042 25" _null_ _null_ _null_ _null_ _null_ textregexeq _null_ _null_ _null_ )
+insert ( 1659 bpcharregexne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1042 25" _null_ _null_ _null_ _null_ _null_ textregexne _null_ _null_ _null_ )
+insert ( 1660 bpchariclike 11 10 12 1 0 0 1025 f f f t f i s 2 0 16 "1042 25" _null_ _null_ _null_ _null_ _null_ texticlike _null_ _null_ _null_ )
+insert ( 1661 bpcharicnlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1042 25" _null_ _null_ _null_ _null_ _null_ texticnlike _null_ _null_ _null_ )
+insert ( 868 strpos 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "25 25" _null_ _null_ _null_ _null_ _null_ textpos _null_ _null_ _null_ )
+insert ( 870 lower 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ lower _null_ _null_ _null_ )
+insert ( 871 upper 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ upper _null_ _null_ _null_ )
+insert ( 872 initcap 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ initcap _null_ _null_ _null_ )
+insert ( 873 lpad 11 10 12 1 0 0 0 f f f t f i s 3 0 25 "25 23 25" _null_ _null_ _null_ _null_ _null_ lpad _null_ _null_ _null_ )
+insert ( 874 rpad 11 10 12 1 0 0 0 f f f t f i s 3 0 25 "25 23 25" _null_ _null_ _null_ _null_ _null_ rpad _null_ _null_ _null_ )
+insert ( 875 ltrim 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ ltrim _null_ _null_ _null_ )
+insert ( 876 rtrim 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ rtrim _null_ _null_ _null_ )
+insert ( 877 substr 11 10 12 1 0 0 0 f f f t f i s 3 0 25 "25 23 23" _null_ _null_ _null_ _null_ _null_ text_substr _null_ _null_ _null_ )
+insert ( 878 translate 11 10 12 1 0 0 0 f f f t f i s 3 0 25 "25 25 25" _null_ _null_ _null_ _null_ _null_ translate _null_ _null_ _null_ )
+insert ( 879 lpad 11 10 14 1 0 0 0 f f f t f i s 2 0 25 "25 23" _null_ _null_ _null_ _null_ _null_ "select pg_catalog.lpad($1, $2, '' '')" _null_ _null_ _null_ )
+insert ( 880 rpad 11 10 14 1 0 0 0 f f f t f i s 2 0 25 "25 23" _null_ _null_ _null_ _null_ _null_ "select pg_catalog.rpad($1, $2, '' '')" _null_ _null_ _null_ )
+insert ( 881 ltrim 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ ltrim1 _null_ _null_ _null_ )
+insert ( 882 rtrim 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ rtrim1 _null_ _null_ _null_ )
+insert ( 883 substr 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 23" _null_ _null_ _null_ _null_ _null_ text_substr_no_len _null_ _null_ _null_ )
+insert ( 884 btrim 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ btrim _null_ _null_ _null_ )
+insert ( 885 btrim 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ btrim1 _null_ _null_ _null_ )
+insert ( 936 substring 11 10 12 1 0 0 0 f f f t f i s 3 0 25 "25 23 23" _null_ _null_ _null_ _null_ _null_ text_substr _null_ _null_ _null_ )
+insert ( 937 substring 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 23" _null_ _null_ _null_ _null_ _null_ text_substr_no_len _null_ _null_ _null_ )
+insert ( 2087 replace 11 10 12 1 0 0 0 f f f t f i s 3 0 25 "25 25 25" _null_ _null_ _null_ _null_ _null_ replace_text _null_ _null_ _null_ )
+insert ( 2284 regexp_replace 11 10 12 1 0 0 0 f f f t f i s 3 0 25 "25 25 25" _null_ _null_ _null_ _null_ _null_ textregexreplace_noopt _null_ _null_ _null_ )
+insert ( 2285 regexp_replace 11 10 12 1 0 0 0 f f f t f i s 4 0 25 "25 25 25 25" _null_ _null_ _null_ _null_ _null_ textregexreplace _null_ _null_ _null_ )
+insert ( 3396 regexp_match 11 10 12 1 0 0 0 f f f t f i s 2 0 1009 "25 25" _null_ _null_ _null_ _null_ _null_ regexp_match_no_flags _null_ _null_ _null_ )
+insert ( 3397 regexp_match 11 10 12 1 0 0 0 f f f t f i s 3 0 1009 "25 25 25" _null_ _null_ _null_ _null_ _null_ regexp_match _null_ _null_ _null_ )
+insert ( 2763 regexp_matches 11 10 12 1 1 0 0 f f f t t i s 2 0 1009 "25 25" _null_ _null_ _null_ _null_ _null_ regexp_matches_no_flags _null_ _null_ _null_ )
+insert ( 2764 regexp_matches 11 10 12 1 10 0 0 f f f t t i s 3 0 1009 "25 25 25" _null_ _null_ _null_ _null_ _null_ regexp_matches _null_ _null_ _null_ )
+insert ( 2088 split_part 11 10 12 1 0 0 0 f f f t f i s 3 0 25 "25 25 23" _null_ _null_ _null_ _null_ _null_ split_text _null_ _null_ _null_ )
+insert ( 2765 regexp_split_to_table 11 10 12 1 1000 0 0 f f f t t i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ regexp_split_to_table_no_flags _null_ _null_ _null_ )
+insert ( 2766 regexp_split_to_table 11 10 12 1 1000 0 0 f f f t t i s 3 0 25 "25 25 25" _null_ _null_ _null_ _null_ _null_ regexp_split_to_table _null_ _null_ _null_ )
+insert ( 2767 regexp_split_to_array 11 10 12 1 0 0 0 f f f t f i s 2 0 1009 "25 25" _null_ _null_ _null_ _null_ _null_ regexp_split_to_array_no_flags _null_ _null_ _null_ )
+insert ( 2768 regexp_split_to_array 11 10 12 1 0 0 0 f f f t f i s 3 0 1009 "25 25 25" _null_ _null_ _null_ _null_ _null_ regexp_split_to_array _null_ _null_ _null_ )
+insert ( 2089 to_hex 11 10 12 1 0 0 0 f f f t f i s 1 0 25 23 _null_ _null_ _null_ _null_ _null_ to_hex32 _null_ _null_ _null_ )
+insert ( 2090 to_hex 11 10 12 1 0 0 0 f f f t f i s 1 0 25 20 _null_ _null_ _null_ _null_ _null_ to_hex64 _null_ _null_ _null_ )
+insert ( 1039 getdatabaseencoding 11 10 12 1 0 0 0 f f f t f s s 0 0 19 "" _null_ _null_ _null_ _null_ _null_ getdatabaseencoding _null_ _null_ _null_ )
+insert ( 810 pg_client_encoding 11 10 12 1 0 0 0 f f f t f s s 0 0 19 "" _null_ _null_ _null_ _null_ _null_ pg_client_encoding _null_ _null_ _null_ )
+insert ( 1713 length 11 10 12 1 0 0 0 f f f t f s s 2 0 23 "17 19" _null_ _null_ _null_ _null_ _null_ length_in_encoding _null_ _null_ _null_ )
+insert ( 1714 convert_from 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "17 19" _null_ _null_ _null_ _null_ _null_ pg_convert_from _null_ _null_ _null_ )
+insert ( 1717 convert_to 11 10 12 1 0 0 0 f f f t f s s 2 0 17 "25 19" _null_ _null_ _null_ _null_ _null_ pg_convert_to _null_ _null_ _null_ )
+insert ( 1813 convert 11 10 12 1 0 0 0 f f f t f s s 3 0 17 "17 19 19" _null_ _null_ _null_ _null_ _null_ pg_convert _null_ _null_ _null_ )
+insert ( 1264 pg_char_to_encoding 11 10 12 1 0 0 0 f f f t f s s 1 0 23 19 _null_ _null_ _null_ _null_ _null_ PG_char_to_encoding _null_ _null_ _null_ )
+insert ( 1597 pg_encoding_to_char 11 10 12 1 0 0 0 f f f t f s s 1 0 19 23 _null_ _null_ _null_ _null_ _null_ PG_encoding_to_char _null_ _null_ _null_ )
+insert ( 2319 pg_encoding_max_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ pg_encoding_max_length_sql _null_ _null_ _null_ )
+insert ( 1638 oidgt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oidgt _null_ _null_ _null_ )
+insert ( 1639 oidge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oidge _null_ _null_ _null_ )
+insert ( 1573 pg_get_ruledef 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_ruledef _null_ _null_ _null_ )
+insert ( 1640 pg_get_viewdef 11 10 12 1 0 0 0 f f f t f s r 1 0 25 25 _null_ _null_ _null_ _null_ _null_ pg_get_viewdef_name _null_ _null_ _null_ )
+insert ( 1641 pg_get_viewdef 11 10 12 1 0 0 0 f f f t f s r 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_viewdef _null_ _null_ _null_ )
+insert ( 1642 pg_get_userbyid 11 10 12 1 0 0 0 f f f t f s s 1 0 19 26 _null_ _null_ _null_ _null_ _null_ pg_get_userbyid _null_ _null_ _null_ )
+insert ( 1643 pg_get_indexdef 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_indexdef _null_ _null_ _null_ )
+insert ( 3415 pg_get_statisticsobjdef 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_statisticsobjdef _null_ _null_ _null_ )
+insert ( 3352 pg_get_partkeydef 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_partkeydef _null_ _null_ _null_ )
+insert ( 3408 pg_get_partition_constraintdef 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_partition_constraintdef _null_ _null_ _null_ )
+insert ( 1662 pg_get_triggerdef 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_triggerdef _null_ _null_ _null_ )
+insert ( 1387 pg_get_constraintdef 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_constraintdef _null_ _null_ _null_ )
+insert ( 1716 pg_get_expr 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "194 26" _null_ _null_ _null_ _null_ _null_ pg_get_expr _null_ _null_ _null_ )
+insert ( 1665 pg_get_serial_sequence 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ pg_get_serial_sequence _null_ _null_ _null_ )
+insert ( 2098 pg_get_functiondef 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_functiondef _null_ _null_ _null_ )
+insert ( 2162 pg_get_function_arguments 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_function_arguments _null_ _null_ _null_ )
+insert ( 2232 pg_get_function_identity_arguments 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_function_identity_arguments _null_ _null_ _null_ )
+insert ( 2165 pg_get_function_result 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_get_function_result _null_ _null_ _null_ )
+insert ( 3808 pg_get_function_arg_default 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "26 23" _null_ _null_ _null_ _null_ _null_ pg_get_function_arg_default _null_ _null_ _null_ )
+insert ( 1686 pg_get_keywords 11 10 12 10 400 0 0 f f f t t s s 0 0 2249 "" "{25,18,25}" "{o,o,o}" "{word,catcode,catdesc}" _null_ _null_ pg_get_keywords _null_ _null_ _null_ )
+insert ( 2289 pg_options_to_table 11 10 12 1 3 0 0 f f f t t s s 1 0 2249 1009 "{1009,25,25}" "{i,o,o}" "{options_array,option_name,option_value}" _null_ _null_ pg_options_to_table _null_ _null_ _null_ )
+insert ( 1619 pg_typeof 11 10 12 1 0 0 0 f f f f f s s 1 0 2206 2276 _null_ _null_ _null_ _null_ _null_ pg_typeof _null_ _null_ _null_ )
+insert ( 3162 pg_collation_for 11 10 12 1 0 0 0 f f f f f s s 1 0 25 2276 _null_ _null_ _null_ _null_ _null_ pg_collation_for _null_ _null_ _null_ )
+insert ( 3842 pg_relation_is_updatable 11 10 12 10 0 0 0 f f f t f s s 2 0 23 "2205 16" _null_ _null_ _null_ _null_ _null_ pg_relation_is_updatable _null_ _null_ _null_ )
+insert ( 3843 pg_column_is_updatable 11 10 12 10 0 0 0 f f f t f s s 3 0 16 "2205 21 16" _null_ _null_ _null_ _null_ _null_ pg_column_is_updatable _null_ _null_ _null_ )
+insert ( 6120 pg_get_replica_identity_index 11 10 12 10 0 0 0 f f f t f s s 1 0 2205 2205 _null_ _null_ _null_ _null_ _null_ pg_get_replica_identity_index _null_ _null_ _null_ )
+insert ( 1250 unique_key_recheck 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ unique_key_recheck _null_ _null_ _null_ )
+insert ( 1644 RI_FKey_check_ins 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_check_ins _null_ _null_ _null_ )
+insert ( 1645 RI_FKey_check_upd 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_check_upd _null_ _null_ _null_ )
+insert ( 1646 RI_FKey_cascade_del 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_cascade_del _null_ _null_ _null_ )
+insert ( 1647 RI_FKey_cascade_upd 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_cascade_upd _null_ _null_ _null_ )
+insert ( 1648 RI_FKey_restrict_del 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_restrict_del _null_ _null_ _null_ )
+insert ( 1649 RI_FKey_restrict_upd 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_restrict_upd _null_ _null_ _null_ )
+insert ( 1650 RI_FKey_setnull_del 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_setnull_del _null_ _null_ _null_ )
+insert ( 1651 RI_FKey_setnull_upd 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_setnull_upd _null_ _null_ _null_ )
+insert ( 1652 RI_FKey_setdefault_del 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_setdefault_del _null_ _null_ _null_ )
+insert ( 1653 RI_FKey_setdefault_upd 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_setdefault_upd _null_ _null_ _null_ )
+insert ( 1654 RI_FKey_noaction_del 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_noaction_del _null_ _null_ _null_ )
+insert ( 1655 RI_FKey_noaction_upd 11 10 12 1 0 0 0 f f f t f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ RI_FKey_noaction_upd _null_ _null_ _null_ )
+insert ( 1666 varbiteq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1562 1562" _null_ _null_ _null_ _null_ _null_ biteq _null_ _null_ _null_ )
+insert ( 1667 varbitne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1562 1562" _null_ _null_ _null_ _null_ _null_ bitne _null_ _null_ _null_ )
+insert ( 1668 varbitge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1562 1562" _null_ _null_ _null_ _null_ _null_ bitge _null_ _null_ _null_ )
+insert ( 1669 varbitgt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1562 1562" _null_ _null_ _null_ _null_ _null_ bitgt _null_ _null_ _null_ )
+insert ( 1670 varbitle 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1562 1562" _null_ _null_ _null_ _null_ _null_ bitle _null_ _null_ _null_ )
+insert ( 1671 varbitlt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1562 1562" _null_ _null_ _null_ _null_ _null_ bitlt _null_ _null_ _null_ )
+insert ( 1672 varbitcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1562 1562" _null_ _null_ _null_ _null_ _null_ bitcmp _null_ _null_ _null_ )
+insert ( 1673 bitand 11 10 12 1 0 0 0 f f f t f i s 2 0 1560 "1560 1560" _null_ _null_ _null_ _null_ _null_ bit_and _null_ _null_ _null_ )
+insert ( 1674 bitor 11 10 12 1 0 0 0 f f f t f i s 2 0 1560 "1560 1560" _null_ _null_ _null_ _null_ _null_ bit_or _null_ _null_ _null_ )
+insert ( 1675 bitxor 11 10 12 1 0 0 0 f f f t f i s 2 0 1560 "1560 1560" _null_ _null_ _null_ _null_ _null_ bitxor _null_ _null_ _null_ )
+insert ( 1676 bitnot 11 10 12 1 0 0 0 f f f t f i s 1 0 1560 1560 _null_ _null_ _null_ _null_ _null_ bitnot _null_ _null_ _null_ )
+insert ( 1677 bitshiftleft 11 10 12 1 0 0 0 f f f t f i s 2 0 1560 "1560 23" _null_ _null_ _null_ _null_ _null_ bitshiftleft _null_ _null_ _null_ )
+insert ( 1678 bitshiftright 11 10 12 1 0 0 0 f f f t f i s 2 0 1560 "1560 23" _null_ _null_ _null_ _null_ _null_ bitshiftright _null_ _null_ _null_ )
+insert ( 1679 bitcat 11 10 12 1 0 0 0 f f f t f i s 2 0 1562 "1562 1562" _null_ _null_ _null_ _null_ _null_ bitcat _null_ _null_ _null_ )
+insert ( 1680 substring 11 10 12 1 0 0 0 f f f t f i s 3 0 1560 "1560 23 23" _null_ _null_ _null_ _null_ _null_ bitsubstr _null_ _null_ _null_ )
+insert ( 1681 length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1560 _null_ _null_ _null_ _null_ _null_ bitlength _null_ _null_ _null_ )
+insert ( 1682 octet_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1560 _null_ _null_ _null_ _null_ _null_ bitoctetlength _null_ _null_ _null_ )
+insert ( 1683 bit 11 10 12 1 0 0 0 f f f t f i s 2 0 1560 "23 23" _null_ _null_ _null_ _null_ _null_ bitfromint4 _null_ _null_ _null_ )
+insert ( 1684 int4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1560 _null_ _null_ _null_ _null_ _null_ bittoint4 _null_ _null_ _null_ )
+insert ( 1685 bit 11 10 12 1 0 0 0 f f f t f i s 3 0 1560 "1560 23 16" _null_ _null_ _null_ _null_ _null_ bit _null_ _null_ _null_ )
+insert ( 3158 varbit_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ varbit_support _null_ _null_ _null_ )
+insert ( 1687 varbit 11 10 12 1 0 0 3158 f f f t f i s 3 0 1562 "1562 23 16" _null_ _null_ _null_ _null_ _null_ varbit _null_ _null_ _null_ )
+insert ( 1698 position 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "1560 1560" _null_ _null_ _null_ _null_ _null_ bitposition _null_ _null_ _null_ )
+insert ( 1699 substring 11 10 12 1 0 0 0 f f f t f i s 2 0 1560 "1560 23" _null_ _null_ _null_ _null_ _null_ bitsubstr_no_len _null_ _null_ _null_ )
+insert ( 3030 overlay 11 10 12 1 0 0 0 f f f t f i s 4 0 1560 "1560 1560 23 23" _null_ _null_ _null_ _null_ _null_ bitoverlay _null_ _null_ _null_ )
+insert ( 3031 overlay 11 10 12 1 0 0 0 f f f t f i s 3 0 1560 "1560 1560 23" _null_ _null_ _null_ _null_ _null_ bitoverlay_no_len _null_ _null_ _null_ )
+insert ( 3032 get_bit 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "1560 23" _null_ _null_ _null_ _null_ _null_ bitgetbit _null_ _null_ _null_ )
+insert ( 3033 set_bit 11 10 12 1 0 0 0 f f f t f i s 3 0 1560 "1560 23 23" _null_ _null_ _null_ _null_ _null_ bitsetbit _null_ _null_ _null_ )
+insert ( 436 macaddr_in 11 10 12 1 0 0 0 f f f t f i s 1 0 829 2275 _null_ _null_ _null_ _null_ _null_ macaddr_in _null_ _null_ _null_ )
+insert ( 437 macaddr_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 829 _null_ _null_ _null_ _null_ _null_ macaddr_out _null_ _null_ _null_ )
+insert ( 753 trunc 11 10 12 1 0 0 0 f f f t f i s 1 0 829 829 _null_ _null_ _null_ _null_ _null_ macaddr_trunc _null_ _null_ _null_ )
+insert ( 830 macaddr_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_eq _null_ _null_ _null_ )
+insert ( 831 macaddr_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_lt _null_ _null_ _null_ )
+insert ( 832 macaddr_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_le _null_ _null_ _null_ )
+insert ( 833 macaddr_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_gt _null_ _null_ _null_ )
+insert ( 834 macaddr_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_ge _null_ _null_ _null_ )
+insert ( 835 macaddr_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_ne _null_ _null_ _null_ )
+insert ( 836 macaddr_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_cmp _null_ _null_ _null_ )
+insert ( 3144 macaddr_not 11 10 12 1 0 0 0 f f f t f i s 1 0 829 829 _null_ _null_ _null_ _null_ _null_ macaddr_not _null_ _null_ _null_ )
+insert ( 3145 macaddr_and 11 10 12 1 0 0 0 f f f t f i s 2 0 829 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_and _null_ _null_ _null_ )
+insert ( 3146 macaddr_or 11 10 12 1 0 0 0 f f f t f i s 2 0 829 "829 829" _null_ _null_ _null_ _null_ _null_ macaddr_or _null_ _null_ _null_ )
+insert ( 3359 macaddr_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ macaddr_sortsupport _null_ _null_ _null_ )
+insert ( 4110 macaddr8_in 11 10 12 1 0 0 0 f f f t f i s 1 0 774 2275 _null_ _null_ _null_ _null_ _null_ macaddr8_in _null_ _null_ _null_ )
+insert ( 4111 macaddr8_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 774 _null_ _null_ _null_ _null_ _null_ macaddr8_out _null_ _null_ _null_ )
+insert ( 4112 trunc 11 10 12 1 0 0 0 f f f t f i s 1 0 774 774 _null_ _null_ _null_ _null_ _null_ macaddr8_trunc _null_ _null_ _null_ )
+insert ( 4113 macaddr8_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_eq _null_ _null_ _null_ )
+insert ( 4114 macaddr8_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_lt _null_ _null_ _null_ )
+insert ( 4115 macaddr8_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_le _null_ _null_ _null_ )
+insert ( 4116 macaddr8_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_gt _null_ _null_ _null_ )
+insert ( 4117 macaddr8_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_ge _null_ _null_ _null_ )
+insert ( 4118 macaddr8_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_ne _null_ _null_ _null_ )
+insert ( 4119 macaddr8_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_cmp _null_ _null_ _null_ )
+insert ( 4120 macaddr8_not 11 10 12 1 0 0 0 f f f t f i s 1 0 774 774 _null_ _null_ _null_ _null_ _null_ macaddr8_not _null_ _null_ _null_ )
+insert ( 4121 macaddr8_and 11 10 12 1 0 0 0 f f f t f i s 2 0 774 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_and _null_ _null_ _null_ )
+insert ( 4122 macaddr8_or 11 10 12 1 0 0 0 f f f t f i s 2 0 774 "774 774" _null_ _null_ _null_ _null_ _null_ macaddr8_or _null_ _null_ _null_ )
+insert ( 4123 macaddr8 11 10 12 1 0 0 0 f f f t f i s 1 0 774 829 _null_ _null_ _null_ _null_ _null_ macaddrtomacaddr8 _null_ _null_ _null_ )
+insert ( 4124 macaddr 11 10 12 1 0 0 0 f f f t f i s 1 0 829 774 _null_ _null_ _null_ _null_ _null_ macaddr8tomacaddr _null_ _null_ _null_ )
+insert ( 4125 macaddr8_set7bit 11 10 12 1 0 0 0 f f f t f i s 1 0 774 774 _null_ _null_ _null_ _null_ _null_ macaddr8_set7bit _null_ _null_ _null_ )
+insert ( 910 inet_in 11 10 12 1 0 0 0 f f f t f i s 1 0 869 2275 _null_ _null_ _null_ _null_ _null_ inet_in _null_ _null_ _null_ )
+insert ( 911 inet_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 869 _null_ _null_ _null_ _null_ _null_ inet_out _null_ _null_ _null_ )
+insert ( 1267 cidr_in 11 10 12 1 0 0 0 f f f t f i s 1 0 650 2275 _null_ _null_ _null_ _null_ _null_ cidr_in _null_ _null_ _null_ )
+insert ( 1427 cidr_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 650 _null_ _null_ _null_ _null_ _null_ cidr_out _null_ _null_ _null_ )
+insert ( 920 network_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_eq _null_ _null_ _null_ )
+insert ( 921 network_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_lt _null_ _null_ _null_ )
+insert ( 922 network_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_le _null_ _null_ _null_ )
+insert ( 923 network_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_gt _null_ _null_ _null_ )
+insert ( 924 network_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_ge _null_ _null_ _null_ )
+insert ( 925 network_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_ne _null_ _null_ _null_ )
+insert ( 3562 network_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 869 "869 869" _null_ _null_ _null_ _null_ _null_ network_larger _null_ _null_ _null_ )
+insert ( 3563 network_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 869 "869 869" _null_ _null_ _null_ _null_ _null_ network_smaller _null_ _null_ _null_ )
+insert ( 926 network_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "869 869" _null_ _null_ _null_ _null_ _null_ network_cmp _null_ _null_ _null_ )
+insert ( 927 network_sub 11 10 12 1 0 0 1173 f f f t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_sub _null_ _null_ _null_ )
+insert ( 928 network_subeq 11 10 12 1 0 0 1173 f f f t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_subeq _null_ _null_ _null_ )
+insert ( 929 network_sup 11 10 12 1 0 0 1173 f f f t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_sup _null_ _null_ _null_ )
+insert ( 930 network_supeq 11 10 12 1 0 0 1173 f f f t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_supeq _null_ _null_ _null_ )
+insert ( 1173 network_subset_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ network_subset_support _null_ _null_ _null_ )
+insert ( 3551 network_overlap 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ network_overlap _null_ _null_ _null_ )
+insert ( 5033 network_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ network_sortsupport _null_ _null_ _null_ )
+insert ( 598 abbrev 11 10 12 1 0 0 0 f f f t f i s 1 0 25 869 _null_ _null_ _null_ _null_ _null_ inet_abbrev _null_ _null_ _null_ )
+insert ( 599 abbrev 11 10 12 1 0 0 0 f f f t f i s 1 0 25 650 _null_ _null_ _null_ _null_ _null_ cidr_abbrev _null_ _null_ _null_ )
+insert ( 605 set_masklen 11 10 12 1 0 0 0 f f f t f i s 2 0 869 "869 23" _null_ _null_ _null_ _null_ _null_ inet_set_masklen _null_ _null_ _null_ )
+insert ( 635 set_masklen 11 10 12 1 0 0 0 f f f t f i s 2 0 650 "650 23" _null_ _null_ _null_ _null_ _null_ cidr_set_masklen _null_ _null_ _null_ )
+insert ( 711 family 11 10 12 1 0 0 0 f f f t f i s 1 0 23 869 _null_ _null_ _null_ _null_ _null_ network_family _null_ _null_ _null_ )
+insert ( 683 network 11 10 12 1 0 0 0 f f f t f i s 1 0 650 869 _null_ _null_ _null_ _null_ _null_ network_network _null_ _null_ _null_ )
+insert ( 696 netmask 11 10 12 1 0 0 0 f f f t f i s 1 0 869 869 _null_ _null_ _null_ _null_ _null_ network_netmask _null_ _null_ _null_ )
+insert ( 697 masklen 11 10 12 1 0 0 0 f f f t f i s 1 0 23 869 _null_ _null_ _null_ _null_ _null_ network_masklen _null_ _null_ _null_ )
+insert ( 698 broadcast 11 10 12 1 0 0 0 f f f t f i s 1 0 869 869 _null_ _null_ _null_ _null_ _null_ network_broadcast _null_ _null_ _null_ )
+insert ( 699 host 11 10 12 1 0 0 0 f f f t f i s 1 0 25 869 _null_ _null_ _null_ _null_ _null_ network_host _null_ _null_ _null_ )
+insert ( 730 text 11 10 12 1 0 0 0 f f f t f i s 1 0 25 869 _null_ _null_ _null_ _null_ _null_ network_show _null_ _null_ _null_ )
+insert ( 1362 hostmask 11 10 12 1 0 0 0 f f f t f i s 1 0 869 869 _null_ _null_ _null_ _null_ _null_ network_hostmask _null_ _null_ _null_ )
+insert ( 1715 cidr 11 10 12 1 0 0 0 f f f t f i s 1 0 650 869 _null_ _null_ _null_ _null_ _null_ inet_to_cidr _null_ _null_ _null_ )
+insert ( 2196 inet_client_addr 11 10 12 1 0 0 0 f f f f f s r 0 0 869 "" _null_ _null_ _null_ _null_ _null_ inet_client_addr _null_ _null_ _null_ )
+insert ( 2197 inet_client_port 11 10 12 1 0 0 0 f f f f f s r 0 0 23 "" _null_ _null_ _null_ _null_ _null_ inet_client_port _null_ _null_ _null_ )
+insert ( 2198 inet_server_addr 11 10 12 1 0 0 0 f f f f f s s 0 0 869 "" _null_ _null_ _null_ _null_ _null_ inet_server_addr _null_ _null_ _null_ )
+insert ( 2199 inet_server_port 11 10 12 1 0 0 0 f f f f f s s 0 0 23 "" _null_ _null_ _null_ _null_ _null_ inet_server_port _null_ _null_ _null_ )
+insert ( 2627 inetnot 11 10 12 1 0 0 0 f f f t f i s 1 0 869 869 _null_ _null_ _null_ _null_ _null_ inetnot _null_ _null_ _null_ )
+insert ( 2628 inetand 11 10 12 1 0 0 0 f f f t f i s 2 0 869 "869 869" _null_ _null_ _null_ _null_ _null_ inetand _null_ _null_ _null_ )
+insert ( 2629 inetor 11 10 12 1 0 0 0 f f f t f i s 2 0 869 "869 869" _null_ _null_ _null_ _null_ _null_ inetor _null_ _null_ _null_ )
+insert ( 2630 inetpl 11 10 12 1 0 0 0 f f f t f i s 2 0 869 "869 20" _null_ _null_ _null_ _null_ _null_ inetpl _null_ _null_ _null_ )
+insert ( 2631 int8pl_inet 11 10 14 1 0 0 0 f f f t f i s 2 0 869 "20 869" _null_ _null_ _null_ _null_ _null_ "select $2 + $1" _null_ _null_ _null_ )
+insert ( 2632 inetmi_int8 11 10 12 1 0 0 0 f f f t f i s 2 0 869 "869 20" _null_ _null_ _null_ _null_ _null_ inetmi_int8 _null_ _null_ _null_ )
+insert ( 2633 inetmi 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "869 869" _null_ _null_ _null_ _null_ _null_ inetmi _null_ _null_ _null_ )
+insert ( 4071 inet_same_family 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ inet_same_family _null_ _null_ _null_ )
+insert ( 4063 inet_merge 11 10 12 1 0 0 0 f f f t f i s 2 0 650 "869 869" _null_ _null_ _null_ _null_ _null_ inet_merge _null_ _null_ _null_ )
+insert ( 3553 inet_gist_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 869 21 26 2281" _null_ _null_ _null_ _null_ _null_ inet_gist_consistent _null_ _null_ _null_ )
+insert ( 3554 inet_gist_union 11 10 12 1 0 0 0 f f f t f i s 2 0 869 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_gist_union _null_ _null_ _null_ )
+insert ( 3555 inet_gist_compress 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ inet_gist_compress _null_ _null_ _null_ )
+insert ( 3573 inet_gist_fetch 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ inet_gist_fetch _null_ _null_ _null_ )
+insert ( 3557 inet_gist_penalty 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ inet_gist_penalty _null_ _null_ _null_ )
+insert ( 3558 inet_gist_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_gist_picksplit _null_ _null_ _null_ )
+insert ( 3559 inet_gist_same 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "869 869 2281" _null_ _null_ _null_ _null_ _null_ inet_gist_same _null_ _null_ _null_ )
+insert ( 3795 inet_spg_config 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_config _null_ _null_ _null_ )
+insert ( 3796 inet_spg_choose 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_choose _null_ _null_ _null_ )
+insert ( 3797 inet_spg_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_picksplit _null_ _null_ _null_ )
+insert ( 3798 inet_spg_inner_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_inner_consistent _null_ _null_ _null_ )
+insert ( 3799 inet_spg_leaf_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2281 2281" _null_ _null_ _null_ _null_ _null_ inet_spg_leaf_consistent _null_ _null_ _null_ )
+insert ( 3560 networksel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ networksel _null_ _null_ _null_ )
+insert ( 3561 networkjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ networkjoinsel _null_ _null_ _null_ )
+insert ( 1690 time_mi_time 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1083 1083" _null_ _null_ _null_ _null_ _null_ time_mi_time _null_ _null_ _null_ )
+insert ( 1691 boolle 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "16 16" _null_ _null_ _null_ _null_ _null_ boolle _null_ _null_ _null_ )
+insert ( 1692 boolge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "16 16" _null_ _null_ _null_ _null_ _null_ boolge _null_ _null_ _null_ )
+insert ( 1693 btboolcmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "16 16" _null_ _null_ _null_ _null_ _null_ btboolcmp _null_ _null_ _null_ )
+insert ( 1688 time_hash 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1083 _null_ _null_ _null_ _null_ _null_ time_hash _null_ _null_ _null_ )
+insert ( 3409 time_hash_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "1083 20" _null_ _null_ _null_ _null_ _null_ time_hash_extended _null_ _null_ _null_ )
+insert ( 1696 timetz_hash 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1266 _null_ _null_ _null_ _null_ _null_ timetz_hash _null_ _null_ _null_ )
+insert ( 3410 timetz_hash_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "1266 20" _null_ _null_ _null_ _null_ _null_ timetz_hash_extended _null_ _null_ _null_ )
+insert ( 1697 interval_hash 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1186 _null_ _null_ _null_ _null_ _null_ interval_hash _null_ _null_ _null_ )
+insert ( 3418 interval_hash_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "1186 20" _null_ _null_ _null_ _null_ _null_ interval_hash_extended _null_ _null_ _null_ )
+insert ( 1701 numeric_in 11 10 12 1 0 0 0 f f f t f i s 3 0 1700 "2275 26 23" _null_ _null_ _null_ _null_ _null_ numeric_in _null_ _null_ _null_ )
+insert ( 1702 numeric_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 1700 _null_ _null_ _null_ _null_ _null_ numeric_out _null_ _null_ _null_ )
+insert ( 2917 numerictypmodin 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1263 _null_ _null_ _null_ _null_ _null_ numerictypmodin _null_ _null_ _null_ )
+insert ( 2918 numerictypmodout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 23 _null_ _null_ _null_ _null_ _null_ numerictypmodout _null_ _null_ _null_ )
+insert ( 3157 numeric_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ numeric_support _null_ _null_ _null_ )
+insert ( 1703 numeric 11 10 12 1 0 0 3157 f f f t f i s 2 0 1700 "1700 23" _null_ _null_ _null_ _null_ _null_ numeric _null_ _null_ _null_ )
+insert ( 1704 numeric_abs 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_abs _null_ _null_ _null_ )
+insert ( 1705 abs 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_abs _null_ _null_ _null_ )
+insert ( 1706 sign 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_sign _null_ _null_ _null_ )
+insert ( 1707 round 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 23" _null_ _null_ _null_ _null_ _null_ numeric_round _null_ _null_ _null_ )
+insert ( 1708 round 11 10 14 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.round($1,0)" _null_ _null_ _null_ )
+insert ( 1709 trunc 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 23" _null_ _null_ _null_ _null_ _null_ numeric_trunc _null_ _null_ _null_ )
+insert ( 1710 trunc 11 10 14 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.trunc($1,0)" _null_ _null_ _null_ )
+insert ( 1711 ceil 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_ceil _null_ _null_ _null_ )
+insert ( 2167 ceiling 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_ceil _null_ _null_ _null_ )
+insert ( 1712 floor 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_floor _null_ _null_ _null_ )
+insert ( 1718 numeric_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_eq _null_ _null_ _null_ )
+insert ( 1719 numeric_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_ne _null_ _null_ _null_ )
+insert ( 1720 numeric_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_gt _null_ _null_ _null_ )
+insert ( 1721 numeric_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_ge _null_ _null_ _null_ )
+insert ( 1722 numeric_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_lt _null_ _null_ _null_ )
+insert ( 1723 numeric_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_le _null_ _null_ _null_ )
+insert ( 1724 numeric_add 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_add _null_ _null_ _null_ )
+insert ( 1725 numeric_sub 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_sub _null_ _null_ _null_ )
+insert ( 1726 numeric_mul 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_mul _null_ _null_ _null_ )
+insert ( 1727 numeric_div 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_div _null_ _null_ _null_ )
+insert ( 1728 mod 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_mod _null_ _null_ _null_ )
+insert ( 1729 numeric_mod 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_mod _null_ _null_ _null_ )
+insert ( 5048 gcd 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_gcd _null_ _null_ _null_ )
+insert ( 5049 lcm 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_lcm _null_ _null_ _null_ )
+insert ( 1730 sqrt 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_sqrt _null_ _null_ _null_ )
+insert ( 1731 numeric_sqrt 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_sqrt _null_ _null_ _null_ )
+insert ( 1732 exp 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_exp _null_ _null_ _null_ )
+insert ( 1733 numeric_exp 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_exp _null_ _null_ _null_ )
+insert ( 1734 ln 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_ln _null_ _null_ _null_ )
+insert ( 1735 numeric_ln 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_ln _null_ _null_ _null_ )
+insert ( 1736 log 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_log _null_ _null_ _null_ )
+insert ( 1737 numeric_log 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_log _null_ _null_ _null_ )
+insert ( 1738 pow 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_power _null_ _null_ _null_ )
+insert ( 2169 power 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_power _null_ _null_ _null_ )
+insert ( 1739 numeric_power 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_power _null_ _null_ _null_ )
+insert ( 3281 scale 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1700 _null_ _null_ _null_ _null_ _null_ numeric_scale _null_ _null_ _null_ )
+insert ( 5042 min_scale 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1700 _null_ _null_ _null_ _null_ _null_ numeric_min_scale _null_ _null_ _null_ )
+insert ( 5043 trim_scale 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_trim_scale _null_ _null_ _null_ )
+insert ( 1740 numeric 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 23 _null_ _null_ _null_ _null_ _null_ int4_numeric _null_ _null_ _null_ )
+insert ( 1741 log 11 10 14 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.log(10, $1)" _null_ _null_ _null_ )
+insert ( 1481 log10 11 10 14 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.log(10, $1)" _null_ _null_ _null_ )
+insert ( 1742 numeric 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 700 _null_ _null_ _null_ _null_ _null_ float4_numeric _null_ _null_ _null_ )
+insert ( 1743 numeric 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 701 _null_ _null_ _null_ _null_ _null_ float8_numeric _null_ _null_ _null_ )
+insert ( 1744 int4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1700 _null_ _null_ _null_ _null_ _null_ numeric_int4 _null_ _null_ _null_ )
+insert ( 1745 float4 11 10 12 1 0 0 0 f f f t f i s 1 0 700 1700 _null_ _null_ _null_ _null_ _null_ numeric_float4 _null_ _null_ _null_ )
+insert ( 1746 float8 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1700 _null_ _null_ _null_ _null_ _null_ numeric_float8 _null_ _null_ _null_ )
+insert ( 1973 div 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_div_trunc _null_ _null_ _null_ )
+insert ( 1980 numeric_div_trunc 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_div_trunc _null_ _null_ _null_ )
+insert ( 2170 width_bucket 11 10 12 1 0 0 0 f f f t f i s 4 0 23 "1700 1700 1700 23" _null_ _null_ _null_ _null_ _null_ width_bucket_numeric _null_ _null_ _null_ )
+insert ( 1747 time_pl_interval 11 10 12 1 0 0 0 f f f t f i s 2 0 1083 "1083 1186" _null_ _null_ _null_ _null_ _null_ time_pl_interval _null_ _null_ _null_ )
+insert ( 1748 time_mi_interval 11 10 12 1 0 0 0 f f f t f i s 2 0 1083 "1083 1186" _null_ _null_ _null_ _null_ _null_ time_mi_interval _null_ _null_ _null_ )
+insert ( 1749 timetz_pl_interval 11 10 12 1 0 0 0 f f f t f i s 2 0 1266 "1266 1186" _null_ _null_ _null_ _null_ _null_ timetz_pl_interval _null_ _null_ _null_ )
+insert ( 1750 timetz_mi_interval 11 10 12 1 0 0 0 f f f t f i s 2 0 1266 "1266 1186" _null_ _null_ _null_ _null_ _null_ timetz_mi_interval _null_ _null_ _null_ )
+insert ( 1764 numeric_inc 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_inc _null_ _null_ _null_ )
+insert ( 1766 numeric_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_smaller _null_ _null_ _null_ )
+insert ( 1767 numeric_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_larger _null_ _null_ _null_ )
+insert ( 1769 numeric_cmp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "1700 1700" _null_ _null_ _null_ _null_ _null_ numeric_cmp _null_ _null_ _null_ )
+insert ( 3283 numeric_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ numeric_sortsupport _null_ _null_ _null_ )
+insert ( 1771 numeric_uminus 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_uminus _null_ _null_ _null_ )
+insert ( 1779 int8 11 10 12 1 0 0 0 f f f t f i s 1 0 20 1700 _null_ _null_ _null_ _null_ _null_ numeric_int8 _null_ _null_ _null_ )
+insert ( 1781 numeric 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ int8_numeric _null_ _null_ _null_ )
+insert ( 1782 numeric 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 21 _null_ _null_ _null_ _null_ _null_ int2_numeric _null_ _null_ _null_ )
+insert ( 1783 int2 11 10 12 1 0 0 0 f f f t f i s 1 0 21 1700 _null_ _null_ _null_ _null_ _null_ numeric_int2 _null_ _null_ _null_ )
+insert ( 3556 bool 11 10 12 1 0 0 0 f f f t f i s 1 0 16 3802 _null_ _null_ _null_ _null_ _null_ jsonb_bool _null_ _null_ _null_ )
+insert ( 3449 numeric 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 3802 _null_ _null_ _null_ _null_ _null_ jsonb_numeric _null_ _null_ _null_ )
+insert ( 3450 int2 11 10 12 1 0 0 0 f f f t f i s 1 0 21 3802 _null_ _null_ _null_ _null_ _null_ jsonb_int2 _null_ _null_ _null_ )
+insert ( 3451 int4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 3802 _null_ _null_ _null_ _null_ _null_ jsonb_int4 _null_ _null_ _null_ )
+insert ( 3452 int8 11 10 12 1 0 0 0 f f f t f i s 1 0 20 3802 _null_ _null_ _null_ _null_ _null_ jsonb_int8 _null_ _null_ _null_ )
+insert ( 3453 float4 11 10 12 1 0 0 0 f f f t f i s 1 0 700 3802 _null_ _null_ _null_ _null_ _null_ jsonb_float4 _null_ _null_ _null_ )
+insert ( 2580 float8 11 10 12 1 0 0 0 f f f t f i s 1 0 701 3802 _null_ _null_ _null_ _null_ _null_ jsonb_float8 _null_ _null_ _null_ )
+insert ( 1770 to_char 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "1184 25" _null_ _null_ _null_ _null_ _null_ timestamptz_to_char _null_ _null_ _null_ )
+insert ( 1772 to_char 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "1700 25" _null_ _null_ _null_ _null_ _null_ numeric_to_char _null_ _null_ _null_ )
+insert ( 1773 to_char 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "23 25" _null_ _null_ _null_ _null_ _null_ int4_to_char _null_ _null_ _null_ )
+insert ( 1774 to_char 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "20 25" _null_ _null_ _null_ _null_ _null_ int8_to_char _null_ _null_ _null_ )
+insert ( 1775 to_char 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "700 25" _null_ _null_ _null_ _null_ _null_ float4_to_char _null_ _null_ _null_ )
+insert ( 1776 to_char 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "701 25" _null_ _null_ _null_ _null_ _null_ float8_to_char _null_ _null_ _null_ )
+insert ( 1777 to_number 11 10 12 1 0 0 0 f f f t f s s 2 0 1700 "25 25" _null_ _null_ _null_ _null_ _null_ numeric_to_number _null_ _null_ _null_ )
+insert ( 1778 to_timestamp 11 10 12 1 0 0 0 f f f t f s s 2 0 1184 "25 25" _null_ _null_ _null_ _null_ _null_ to_timestamp _null_ _null_ _null_ )
+insert ( 1780 to_date 11 10 12 1 0 0 0 f f f t f s s 2 0 1082 "25 25" _null_ _null_ _null_ _null_ _null_ to_date _null_ _null_ _null_ )
+insert ( 1768 to_char 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "1186 25" _null_ _null_ _null_ _null_ _null_ interval_to_char _null_ _null_ _null_ )
+insert ( 1282 quote_ident 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ quote_ident _null_ _null_ _null_ )
+insert ( 1283 quote_literal 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ quote_literal _null_ _null_ _null_ )
+insert ( 1285 quote_literal 11 10 14 1 0 0 0 f f f t f s s 1 0 25 2283 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.quote_literal($1::pg_catalog.text)" _null_ _null_ _null_ )
+insert ( 1289 quote_nullable 11 10 12 1 0 0 0 f f f f f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ quote_nullable _null_ _null_ _null_ )
+insert ( 1290 quote_nullable 11 10 14 1 0 0 0 f f f f f s s 1 0 25 2283 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.quote_nullable($1::pg_catalog.text)" _null_ _null_ _null_ )
+insert ( 1798 oidin 11 10 12 1 0 0 0 f f f t f i s 1 0 26 2275 _null_ _null_ _null_ _null_ _null_ oidin _null_ _null_ _null_ )
+insert ( 1799 oidout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 26 _null_ _null_ _null_ _null_ _null_ oidout _null_ _null_ _null_ )
+insert ( 3058 concat 11 10 12 1 0 2276 0 f f f f f s s 1 0 25 2276 "{2276}" "{v}" _null_ _null_ _null_ text_concat _null_ _null_ _null_ )
+insert ( 3059 concat_ws 11 10 12 1 0 2276 0 f f f f f s s 2 0 25 "25 2276" "{25,2276}" "{i,v}" _null_ _null_ _null_ text_concat_ws _null_ _null_ _null_ )
+insert ( 3060 left 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 23" _null_ _null_ _null_ _null_ _null_ text_left _null_ _null_ _null_ )
+insert ( 3061 right 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 23" _null_ _null_ _null_ _null_ _null_ text_right _null_ _null_ _null_ )
+insert ( 3062 reverse 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ text_reverse _null_ _null_ _null_ )
+insert ( 3539 format 11 10 12 1 0 2276 0 f f f f f s s 2 0 25 "25 2276" "{25,2276}" "{i,v}" _null_ _null_ _null_ text_format _null_ _null_ _null_ )
+insert ( 3540 format 11 10 12 1 0 0 0 f f f f f s s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ text_format_nv _null_ _null_ _null_ )
+insert ( 1810 bit_length 11 10 14 1 0 0 0 f f f t f i s 1 0 23 17 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.octet_length($1) * 8" _null_ _null_ _null_ )
+insert ( 1811 bit_length 11 10 14 1 0 0 0 f f f t f i s 1 0 23 25 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.octet_length($1) * 8" _null_ _null_ _null_ )
+insert ( 1812 bit_length 11 10 14 1 0 0 0 f f f t f i s 1 0 23 1560 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.length($1)" _null_ _null_ _null_ )
+insert ( 1814 iclikesel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ iclikesel _null_ _null_ _null_ )
+insert ( 1815 icnlikesel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ icnlikesel _null_ _null_ _null_ )
+insert ( 1816 iclikejoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ iclikejoinsel _null_ _null_ _null_ )
+insert ( 1817 icnlikejoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ icnlikejoinsel _null_ _null_ _null_ )
+insert ( 1818 regexeqsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ regexeqsel _null_ _null_ _null_ )
+insert ( 1819 likesel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ likesel _null_ _null_ _null_ )
+insert ( 1820 icregexeqsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ icregexeqsel _null_ _null_ _null_ )
+insert ( 1821 regexnesel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ regexnesel _null_ _null_ _null_ )
+insert ( 1822 nlikesel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ nlikesel _null_ _null_ _null_ )
+insert ( 1823 icregexnesel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ icregexnesel _null_ _null_ _null_ )
+insert ( 1824 regexeqjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ regexeqjoinsel _null_ _null_ _null_ )
+insert ( 1825 likejoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ likejoinsel _null_ _null_ _null_ )
+insert ( 1826 icregexeqjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ icregexeqjoinsel _null_ _null_ _null_ )
+insert ( 1827 regexnejoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ regexnejoinsel _null_ _null_ _null_ )
+insert ( 1828 nlikejoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ nlikejoinsel _null_ _null_ _null_ )
+insert ( 1829 icregexnejoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ icregexnejoinsel _null_ _null_ _null_ )
+insert ( 3437 prefixsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ prefixsel _null_ _null_ _null_ )
+insert ( 3438 prefixjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ prefixjoinsel _null_ _null_ _null_ )
+insert ( 1830 float8_avg 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_avg _null_ _null_ _null_ )
+insert ( 2512 float8_var_pop 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_var_pop _null_ _null_ _null_ )
+insert ( 1831 float8_var_samp 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_var_samp _null_ _null_ _null_ )
+insert ( 2513 float8_stddev_pop 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_stddev_pop _null_ _null_ _null_ )
+insert ( 1832 float8_stddev_samp 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_stddev_samp _null_ _null_ _null_ )
+insert ( 1833 numeric_accum 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 1700" _null_ _null_ _null_ _null_ _null_ numeric_accum _null_ _null_ _null_ )
+insert ( 3341 numeric_combine 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ numeric_combine _null_ _null_ _null_ )
+insert ( 2858 numeric_avg_accum 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 1700" _null_ _null_ _null_ _null_ _null_ numeric_avg_accum _null_ _null_ _null_ )
+insert ( 3337 numeric_avg_combine 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ numeric_avg_combine _null_ _null_ _null_ )
+insert ( 2740 numeric_avg_serialize 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2281 _null_ _null_ _null_ _null_ _null_ numeric_avg_serialize _null_ _null_ _null_ )
+insert ( 2741 numeric_avg_deserialize 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_avg_deserialize _null_ _null_ _null_ )
+insert ( 3335 numeric_serialize 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2281 _null_ _null_ _null_ _null_ _null_ numeric_serialize _null_ _null_ _null_ )
+insert ( 3336 numeric_deserialize 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_deserialize _null_ _null_ _null_ )
+insert ( 3548 numeric_accum_inv 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 1700" _null_ _null_ _null_ _null_ _null_ numeric_accum_inv _null_ _null_ _null_ )
+insert ( 1834 int2_accum 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 21" _null_ _null_ _null_ _null_ _null_ int2_accum _null_ _null_ _null_ )
+insert ( 1835 int4_accum 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 23" _null_ _null_ _null_ _null_ _null_ int4_accum _null_ _null_ _null_ )
+insert ( 1836 int8_accum 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ _null_ int8_accum _null_ _null_ _null_ )
+insert ( 3338 numeric_poly_combine 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ numeric_poly_combine _null_ _null_ _null_ )
+insert ( 3339 numeric_poly_serialize 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2281 _null_ _null_ _null_ _null_ _null_ numeric_poly_serialize _null_ _null_ _null_ )
+insert ( 3340 numeric_poly_deserialize 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ numeric_poly_deserialize _null_ _null_ _null_ )
+insert ( 2746 int8_avg_accum 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ _null_ int8_avg_accum _null_ _null_ _null_ )
+insert ( 3567 int2_accum_inv 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 21" _null_ _null_ _null_ _null_ _null_ int2_accum_inv _null_ _null_ _null_ )
+insert ( 3568 int4_accum_inv 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 23" _null_ _null_ _null_ _null_ _null_ int4_accum_inv _null_ _null_ _null_ )
+insert ( 3569 int8_accum_inv 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ _null_ int8_accum_inv _null_ _null_ _null_ )
+insert ( 3387 int8_avg_accum_inv 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 20" _null_ _null_ _null_ _null_ _null_ int8_avg_accum_inv _null_ _null_ _null_ )
+insert ( 2785 int8_avg_combine 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ int8_avg_combine _null_ _null_ _null_ )
+insert ( 2786 int8_avg_serialize 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2281 _null_ _null_ _null_ _null_ _null_ int8_avg_serialize _null_ _null_ _null_ )
+insert ( 2787 int8_avg_deserialize 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "17 2281" _null_ _null_ _null_ _null_ _null_ int8_avg_deserialize _null_ _null_ _null_ )
+insert ( 3324 int4_avg_combine 11 10 12 1 0 0 0 f f f t f i s 2 0 1016 "1016 1016" _null_ _null_ _null_ _null_ _null_ int4_avg_combine _null_ _null_ _null_ )
+insert ( 3178 numeric_sum 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_sum _null_ _null_ _null_ )
+insert ( 1837 numeric_avg 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_avg _null_ _null_ _null_ )
+insert ( 2514 numeric_var_pop 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_var_pop _null_ _null_ _null_ )
+insert ( 1838 numeric_var_samp 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_var_samp _null_ _null_ _null_ )
+insert ( 2596 numeric_stddev_pop 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_stddev_pop _null_ _null_ _null_ )
+insert ( 1839 numeric_stddev_samp 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_stddev_samp _null_ _null_ _null_ )
+insert ( 1840 int2_sum 11 10 12 1 0 0 0 f f f f f i s 2 0 20 "20 21" _null_ _null_ _null_ _null_ _null_ int2_sum _null_ _null_ _null_ )
+insert ( 1841 int4_sum 11 10 12 1 0 0 0 f f f f f i s 2 0 20 "20 23" _null_ _null_ _null_ _null_ _null_ int4_sum _null_ _null_ _null_ )
+insert ( 1842 int8_sum 11 10 12 1 0 0 0 f f f f f i s 2 0 1700 "1700 20" _null_ _null_ _null_ _null_ _null_ int8_sum _null_ _null_ _null_ )
+insert ( 3388 numeric_poly_sum 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_poly_sum _null_ _null_ _null_ )
+insert ( 3389 numeric_poly_avg 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_poly_avg _null_ _null_ _null_ )
+insert ( 3390 numeric_poly_var_pop 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_poly_var_pop _null_ _null_ _null_ )
+insert ( 3391 numeric_poly_var_samp 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_poly_var_samp _null_ _null_ _null_ )
+insert ( 3392 numeric_poly_stddev_pop 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_poly_stddev_pop _null_ _null_ _null_ )
+insert ( 3393 numeric_poly_stddev_samp 11 10 12 1 0 0 0 f f f f f i s 1 0 1700 2281 _null_ _null_ _null_ _null_ _null_ numeric_poly_stddev_samp _null_ _null_ _null_ )
+insert ( 1843 interval_accum 11 10 12 1 0 0 0 f f f t f i s 2 0 1187 "1187 1186" _null_ _null_ _null_ _null_ _null_ interval_accum _null_ _null_ _null_ )
+insert ( 3325 interval_combine 11 10 12 1 0 0 0 f f f t f i s 2 0 1187 "1187 1187" _null_ _null_ _null_ _null_ _null_ interval_combine _null_ _null_ _null_ )
+insert ( 3549 interval_accum_inv 11 10 12 1 0 0 0 f f f t f i s 2 0 1187 "1187 1186" _null_ _null_ _null_ _null_ _null_ interval_accum_inv _null_ _null_ _null_ )
+insert ( 1844 interval_avg 11 10 12 1 0 0 0 f f f t f i s 1 0 1186 1187 _null_ _null_ _null_ _null_ _null_ interval_avg _null_ _null_ _null_ )
+insert ( 1962 int2_avg_accum 11 10 12 1 0 0 0 f f f t f i s 2 0 1016 "1016 21" _null_ _null_ _null_ _null_ _null_ int2_avg_accum _null_ _null_ _null_ )
+insert ( 1963 int4_avg_accum 11 10 12 1 0 0 0 f f f t f i s 2 0 1016 "1016 23" _null_ _null_ _null_ _null_ _null_ int4_avg_accum _null_ _null_ _null_ )
+insert ( 3570 int2_avg_accum_inv 11 10 12 1 0 0 0 f f f t f i s 2 0 1016 "1016 21" _null_ _null_ _null_ _null_ _null_ int2_avg_accum_inv _null_ _null_ _null_ )
+insert ( 3571 int4_avg_accum_inv 11 10 12 1 0 0 0 f f f t f i s 2 0 1016 "1016 23" _null_ _null_ _null_ _null_ _null_ int4_avg_accum_inv _null_ _null_ _null_ )
+insert ( 1964 int8_avg 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1016 _null_ _null_ _null_ _null_ _null_ int8_avg _null_ _null_ _null_ )
+insert ( 3572 int2int4_sum 11 10 12 1 0 0 0 f f f t f i s 1 0 20 1016 _null_ _null_ _null_ _null_ _null_ int2int4_sum _null_ _null_ _null_ )
+insert ( 2805 int8inc_float8_float8 11 10 12 1 0 0 0 f f f t f i s 3 0 20 "20 701 701" _null_ _null_ _null_ _null_ _null_ int8inc_float8_float8 _null_ _null_ _null_ )
+insert ( 2806 float8_regr_accum 11 10 12 1 0 0 0 f f f t f i s 3 0 1022 "1022 701 701" _null_ _null_ _null_ _null_ _null_ float8_regr_accum _null_ _null_ _null_ )
+insert ( 3342 float8_regr_combine 11 10 12 1 0 0 0 f f f t f i s 2 0 1022 "1022 1022" _null_ _null_ _null_ _null_ _null_ float8_regr_combine _null_ _null_ _null_ )
+insert ( 2807 float8_regr_sxx 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_regr_sxx _null_ _null_ _null_ )
+insert ( 2808 float8_regr_syy 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_regr_syy _null_ _null_ _null_ )
+insert ( 2809 float8_regr_sxy 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_regr_sxy _null_ _null_ _null_ )
+insert ( 2810 float8_regr_avgx 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_regr_avgx _null_ _null_ _null_ )
+insert ( 2811 float8_regr_avgy 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_regr_avgy _null_ _null_ _null_ )
+insert ( 2812 float8_regr_r2 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_regr_r2 _null_ _null_ _null_ )
+insert ( 2813 float8_regr_slope 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_regr_slope _null_ _null_ _null_ )
+insert ( 2814 float8_regr_intercept 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_regr_intercept _null_ _null_ _null_ )
+insert ( 2815 float8_covar_pop 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_covar_pop _null_ _null_ _null_ )
+insert ( 2816 float8_covar_samp 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_covar_samp _null_ _null_ _null_ )
+insert ( 2817 float8_corr 11 10 12 1 0 0 0 f f f t f i s 1 0 701 1022 _null_ _null_ _null_ _null_ _null_ float8_corr _null_ _null_ _null_ )
+insert ( 3535 string_agg_transfn 11 10 12 1 0 0 0 f f f f f i s 3 0 2281 "2281 25 25" _null_ _null_ _null_ _null_ _null_ string_agg_transfn _null_ _null_ _null_ )
+insert ( 3536 string_agg_finalfn 11 10 12 1 0 0 0 f f f f f i s 1 0 25 2281 _null_ _null_ _null_ _null_ _null_ string_agg_finalfn _null_ _null_ _null_ )
+insert ( 3538 string_agg 11 10 12 1 0 0 0 a f f f f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3543 bytea_string_agg_transfn 11 10 12 1 0 0 0 f f f f f i s 3 0 2281 "2281 17 17" _null_ _null_ _null_ _null_ _null_ bytea_string_agg_transfn _null_ _null_ _null_ )
+insert ( 3544 bytea_string_agg_finalfn 11 10 12 1 0 0 0 f f f f f i s 1 0 17 2281 _null_ _null_ _null_ _null_ _null_ bytea_string_agg_finalfn _null_ _null_ _null_ )
+insert ( 3545 string_agg 11 10 12 1 0 0 0 a f f f f i s 2 0 17 "17 17" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 1845 to_ascii 11 10 12 1 0 0 0 f f f t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ to_ascii_default _null_ _null_ _null_ )
+insert ( 1846 to_ascii 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 23" _null_ _null_ _null_ _null_ _null_ to_ascii_enc _null_ _null_ _null_ )
+insert ( 1847 to_ascii 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 19" _null_ _null_ _null_ _null_ _null_ to_ascii_encname _null_ _null_ _null_ )
+insert ( 1848 interval_pl_time 11 10 14 1 0 0 0 f f f t f i s 2 0 1083 "1186 1083" _null_ _null_ _null_ _null_ _null_ "select $2 + $1" _null_ _null_ _null_ )
+insert ( 1850 int28eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 20" _null_ _null_ _null_ _null_ _null_ int28eq _null_ _null_ _null_ )
+insert ( 1851 int28ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 20" _null_ _null_ _null_ _null_ _null_ int28ne _null_ _null_ _null_ )
+insert ( 1852 int28lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 20" _null_ _null_ _null_ _null_ _null_ int28lt _null_ _null_ _null_ )
+insert ( 1853 int28gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 20" _null_ _null_ _null_ _null_ _null_ int28gt _null_ _null_ _null_ )
+insert ( 1854 int28le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 20" _null_ _null_ _null_ _null_ _null_ int28le _null_ _null_ _null_ )
+insert ( 1855 int28ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "21 20" _null_ _null_ _null_ _null_ _null_ int28ge _null_ _null_ _null_ )
+insert ( 1856 int82eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 21" _null_ _null_ _null_ _null_ _null_ int82eq _null_ _null_ _null_ )
+insert ( 1857 int82ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 21" _null_ _null_ _null_ _null_ _null_ int82ne _null_ _null_ _null_ )
+insert ( 1858 int82lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 21" _null_ _null_ _null_ _null_ _null_ int82lt _null_ _null_ _null_ )
+insert ( 1859 int82gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 21" _null_ _null_ _null_ _null_ _null_ int82gt _null_ _null_ _null_ )
+insert ( 1860 int82le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 21" _null_ _null_ _null_ _null_ _null_ int82le _null_ _null_ _null_ )
+insert ( 1861 int82ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "20 21" _null_ _null_ _null_ _null_ _null_ int82ge _null_ _null_ _null_ )
+insert ( 1892 int2and 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2and _null_ _null_ _null_ )
+insert ( 1893 int2or 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2or _null_ _null_ _null_ )
+insert ( 1894 int2xor 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 21" _null_ _null_ _null_ _null_ _null_ int2xor _null_ _null_ _null_ )
+insert ( 1895 int2not 11 10 12 1 0 0 0 f f f t f i s 1 0 21 21 _null_ _null_ _null_ _null_ _null_ int2not _null_ _null_ _null_ )
+insert ( 1896 int2shl 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 23" _null_ _null_ _null_ _null_ _null_ int2shl _null_ _null_ _null_ )
+insert ( 1897 int2shr 11 10 12 1 0 0 0 f f f t f i s 2 0 21 "21 23" _null_ _null_ _null_ _null_ _null_ int2shr _null_ _null_ _null_ )
+insert ( 1898 int4and 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4and _null_ _null_ _null_ )
+insert ( 1899 int4or 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4or _null_ _null_ _null_ )
+insert ( 1900 int4xor 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4xor _null_ _null_ _null_ )
+insert ( 1901 int4not 11 10 12 1 0 0 0 f f f t f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ int4not _null_ _null_ _null_ )
+insert ( 1902 int4shl 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4shl _null_ _null_ _null_ )
+insert ( 1903 int4shr 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ int4shr _null_ _null_ _null_ )
+insert ( 1904 int8and 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8and _null_ _null_ _null_ )
+insert ( 1905 int8or 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8or _null_ _null_ _null_ )
+insert ( 1906 int8xor 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ int8xor _null_ _null_ _null_ )
+insert ( 1907 int8not 11 10 12 1 0 0 0 f f f t f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ int8not _null_ _null_ _null_ )
+insert ( 1908 int8shl 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 23" _null_ _null_ _null_ _null_ _null_ int8shl _null_ _null_ _null_ )
+insert ( 1909 int8shr 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "20 23" _null_ _null_ _null_ _null_ _null_ int8shr _null_ _null_ _null_ )
+insert ( 1910 int8up 11 10 12 1 0 0 0 f f f t f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ int8up _null_ _null_ _null_ )
+insert ( 1911 int2up 11 10 12 1 0 0 0 f f f t f i s 1 0 21 21 _null_ _null_ _null_ _null_ _null_ int2up _null_ _null_ _null_ )
+insert ( 1912 int4up 11 10 12 1 0 0 0 f f f t f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ int4up _null_ _null_ _null_ )
+insert ( 1913 float4up 11 10 12 1 0 0 0 f f f t f i s 1 0 700 700 _null_ _null_ _null_ _null_ _null_ float4up _null_ _null_ _null_ )
+insert ( 1914 float8up 11 10 12 1 0 0 0 f f f t f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ float8up _null_ _null_ _null_ )
+insert ( 1915 numeric_uplus 11 10 12 1 0 0 0 f f f t f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ numeric_uplus _null_ _null_ _null_ )
+insert ( 1922 has_table_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_table_privilege_name_name _null_ _null_ _null_ )
+insert ( 1923 has_table_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_table_privilege_name_id _null_ _null_ _null_ )
+insert ( 1924 has_table_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_table_privilege_id_name _null_ _null_ _null_ )
+insert ( 1925 has_table_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_table_privilege_id_id _null_ _null_ _null_ )
+insert ( 1926 has_table_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_table_privilege_name _null_ _null_ _null_ )
+insert ( 1927 has_table_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_table_privilege_id _null_ _null_ _null_ )
+insert ( 2181 has_sequence_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_sequence_privilege_name_name _null_ _null_ _null_ )
+insert ( 2182 has_sequence_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_sequence_privilege_name_id _null_ _null_ _null_ )
+insert ( 2183 has_sequence_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_sequence_privilege_id_name _null_ _null_ _null_ )
+insert ( 2184 has_sequence_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_sequence_privilege_id_id _null_ _null_ _null_ )
+insert ( 2185 has_sequence_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_sequence_privilege_name _null_ _null_ _null_ )
+insert ( 2186 has_sequence_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_sequence_privilege_id _null_ _null_ _null_ )
+insert ( 3012 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "19 25 25 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_name_name_name _null_ _null_ _null_ )
+insert ( 3013 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "19 25 21 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_name_name_attnum _null_ _null_ _null_ )
+insert ( 3014 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "19 26 25 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_name_id_name _null_ _null_ _null_ )
+insert ( 3015 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "19 26 21 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_name_id_attnum _null_ _null_ _null_ )
+insert ( 3016 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "26 25 25 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_id_name_name _null_ _null_ _null_ )
+insert ( 3017 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "26 25 21 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_id_name_attnum _null_ _null_ _null_ )
+insert ( 3018 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "26 26 25 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_id_id_name _null_ _null_ _null_ )
+insert ( 3019 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "26 26 21 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_id_id_attnum _null_ _null_ _null_ )
+insert ( 3020 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "25 25 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_name_name _null_ _null_ _null_ )
+insert ( 3021 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "25 21 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_name_attnum _null_ _null_ _null_ )
+insert ( 3022 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_id_name _null_ _null_ _null_ )
+insert ( 3023 has_column_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 21 25" _null_ _null_ _null_ _null_ _null_ has_column_privilege_id_attnum _null_ _null_ _null_ )
+insert ( 3024 has_any_column_privilege 11 10 12 10 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_any_column_privilege_name_name _null_ _null_ _null_ )
+insert ( 3025 has_any_column_privilege 11 10 12 10 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_any_column_privilege_name_id _null_ _null_ _null_ )
+insert ( 3026 has_any_column_privilege 11 10 12 10 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_any_column_privilege_id_name _null_ _null_ _null_ )
+insert ( 3027 has_any_column_privilege 11 10 12 10 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_any_column_privilege_id_id _null_ _null_ _null_ )
+insert ( 3028 has_any_column_privilege 11 10 12 10 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_any_column_privilege_name _null_ _null_ _null_ )
+insert ( 3029 has_any_column_privilege 11 10 12 10 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_any_column_privilege_id _null_ _null_ _null_ )
+insert ( 3355 pg_ndistinct_in 11 10 12 1 0 0 0 f f f t f i s 1 0 3361 2275 _null_ _null_ _null_ _null_ _null_ pg_ndistinct_in _null_ _null_ _null_ )
+insert ( 3356 pg_ndistinct_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3361 _null_ _null_ _null_ _null_ _null_ pg_ndistinct_out _null_ _null_ _null_ )
+insert ( 3357 pg_ndistinct_recv 11 10 12 1 0 0 0 f f f t f s s 1 0 3361 2281 _null_ _null_ _null_ _null_ _null_ pg_ndistinct_recv _null_ _null_ _null_ )
+insert ( 3358 pg_ndistinct_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 3361 _null_ _null_ _null_ _null_ _null_ pg_ndistinct_send _null_ _null_ _null_ )
+insert ( 3404 pg_dependencies_in 11 10 12 1 0 0 0 f f f t f i s 1 0 3402 2275 _null_ _null_ _null_ _null_ _null_ pg_dependencies_in _null_ _null_ _null_ )
+insert ( 3405 pg_dependencies_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3402 _null_ _null_ _null_ _null_ _null_ pg_dependencies_out _null_ _null_ _null_ )
+insert ( 3406 pg_dependencies_recv 11 10 12 1 0 0 0 f f f t f s s 1 0 3402 2281 _null_ _null_ _null_ _null_ _null_ pg_dependencies_recv _null_ _null_ _null_ )
+insert ( 3407 pg_dependencies_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 3402 _null_ _null_ _null_ _null_ _null_ pg_dependencies_send _null_ _null_ _null_ )
+insert ( 5018 pg_mcv_list_in 11 10 12 1 0 0 0 f f f t f i s 1 0 5017 2275 _null_ _null_ _null_ _null_ _null_ pg_mcv_list_in _null_ _null_ _null_ )
+insert ( 5019 pg_mcv_list_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 5017 _null_ _null_ _null_ _null_ _null_ pg_mcv_list_out _null_ _null_ _null_ )
+insert ( 5020 pg_mcv_list_recv 11 10 12 1 0 0 0 f f f t f s s 1 0 5017 2281 _null_ _null_ _null_ _null_ _null_ pg_mcv_list_recv _null_ _null_ _null_ )
+insert ( 5021 pg_mcv_list_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 5017 _null_ _null_ _null_ _null_ _null_ pg_mcv_list_send _null_ _null_ _null_ )
+insert ( 3427 pg_mcv_list_items 11 10 12 1 1000 0 0 f f f t t s s 1 0 2249 5017 "{5017,23,1009,1000,701,701}" "{i,o,o,o,o,o}" "{mcv_list,index,values,nulls,frequency,base_frequency}" _null_ _null_ pg_stats_ext_mcvlist_items _null_ _null_ _null_ )
+insert ( 1928 pg_stat_get_numscans 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_numscans _null_ _null_ _null_ )
+insert ( 1929 pg_stat_get_tuples_returned 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_tuples_returned _null_ _null_ _null_ )
+insert ( 1930 pg_stat_get_tuples_fetched 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_tuples_fetched _null_ _null_ _null_ )
+insert ( 1931 pg_stat_get_tuples_inserted 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_tuples_inserted _null_ _null_ _null_ )
+insert ( 1932 pg_stat_get_tuples_updated 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_tuples_updated _null_ _null_ _null_ )
+insert ( 1933 pg_stat_get_tuples_deleted 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_tuples_deleted _null_ _null_ _null_ )
+insert ( 1972 pg_stat_get_tuples_hot_updated 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_tuples_hot_updated _null_ _null_ _null_ )
+insert ( 2878 pg_stat_get_live_tuples 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_live_tuples _null_ _null_ _null_ )
+insert ( 2879 pg_stat_get_dead_tuples 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_dead_tuples _null_ _null_ _null_ )
+insert ( 3177 pg_stat_get_mod_since_analyze 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_mod_since_analyze _null_ _null_ _null_ )
+insert ( 5053 pg_stat_get_ins_since_vacuum 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_ins_since_vacuum _null_ _null_ _null_ )
+insert ( 1934 pg_stat_get_blocks_fetched 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_blocks_fetched _null_ _null_ _null_ )
+insert ( 1935 pg_stat_get_blocks_hit 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_blocks_hit _null_ _null_ _null_ )
+insert ( 2781 pg_stat_get_last_vacuum_time 11 10 12 1 0 0 0 f f f t f s r 1 0 1184 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_last_vacuum_time _null_ _null_ _null_ )
+insert ( 2782 pg_stat_get_last_autovacuum_time 11 10 12 1 0 0 0 f f f t f s r 1 0 1184 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_last_autovacuum_time _null_ _null_ _null_ )
+insert ( 2783 pg_stat_get_last_analyze_time 11 10 12 1 0 0 0 f f f t f s r 1 0 1184 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_last_analyze_time _null_ _null_ _null_ )
+insert ( 2784 pg_stat_get_last_autoanalyze_time 11 10 12 1 0 0 0 f f f t f s r 1 0 1184 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_last_autoanalyze_time _null_ _null_ _null_ )
+insert ( 3054 pg_stat_get_vacuum_count 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_vacuum_count _null_ _null_ _null_ )
+insert ( 3055 pg_stat_get_autovacuum_count 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_autovacuum_count _null_ _null_ _null_ )
+insert ( 3056 pg_stat_get_analyze_count 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_analyze_count _null_ _null_ _null_ )
+insert ( 3057 pg_stat_get_autoanalyze_count 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_autoanalyze_count _null_ _null_ _null_ )
+insert ( 1936 pg_stat_get_backend_idset 11 10 12 1 100 0 0 f f f t t s r 0 0 23 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_idset _null_ _null_ _null_ )
+insert ( 2022 pg_stat_get_activity 11 10 12 1 100 0 0 f f f f t s r 1 0 2249 23 "{23,26,23,26,25,25,25,25,25,1184,1184,1184,1184,869,25,23,28,28,25,16,25,25,23,16,25,1700,25,16,25,16,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid}" _null_ _null_ pg_stat_get_activity _null_ _null_ _null_ )
+insert ( 3318 pg_stat_get_progress_info 11 10 12 1 100 0 0 f f f t t s r 1 0 2249 25 "{25,23,26,26,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{cmdtype,pid,datid,relid,param1,param2,param3,param4,param5,param6,param7,param8,param9,param10,param11,param12,param13,param14,param15,param16,param17,param18,param19,param20}" _null_ _null_ pg_stat_get_progress_info _null_ _null_ _null_ )
+insert ( 3099 pg_stat_get_wal_senders 11 10 12 1 10 0 0 f f f f t s r 0 0 2249 "" "{23,25,3220,3220,3220,3220,1186,1186,1186,23,25,1184}" "{o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,state,sent_lsn,write_lsn,flush_lsn,replay_lsn,write_lag,flush_lag,replay_lag,sync_priority,sync_state,reply_time}" _null_ _null_ pg_stat_get_wal_senders _null_ _null_ _null_ )
+insert ( 3317 pg_stat_get_wal_receiver 11 10 12 1 0 0 0 f f f f f s r 0 0 2249 "" "{23,25,3220,23,3220,3220,23,1184,1184,3220,1184,25,25,23,25}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,status,receive_start_lsn,receive_start_tli,written_lsn,flushed_lsn,received_tli,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time,slot_name,sender_host,sender_port,conninfo}" _null_ _null_ pg_stat_get_wal_receiver _null_ _null_ _null_ )
+insert ( 6118 pg_stat_get_subscription 11 10 12 1 0 0 0 f f f f f s r 1 0 2249 26 "{26,26,26,23,3220,1184,1184,3220,1184}" "{i,o,o,o,o,o,o,o,o}" "{subid,subid,relid,pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}" _null_ _null_ pg_stat_get_subscription _null_ _null_ _null_ )
+insert ( 2026 pg_backend_pid 11 10 12 1 0 0 0 f f f t f s r 0 0 23 "" _null_ _null_ _null_ _null_ _null_ pg_backend_pid _null_ _null_ _null_ )
+insert ( 1937 pg_stat_get_backend_pid 11 10 12 1 0 0 0 f f f t f s r 1 0 23 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_pid _null_ _null_ _null_ )
+insert ( 1938 pg_stat_get_backend_dbid 11 10 12 1 0 0 0 f f f t f s r 1 0 26 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_dbid _null_ _null_ _null_ )
+insert ( 1939 pg_stat_get_backend_userid 11 10 12 1 0 0 0 f f f t f s r 1 0 26 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_userid _null_ _null_ _null_ )
+insert ( 1940 pg_stat_get_backend_activity 11 10 12 1 0 0 0 f f f t f s r 1 0 25 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_activity _null_ _null_ _null_ )
+insert ( 2788 pg_stat_get_backend_wait_event_type 11 10 12 1 0 0 0 f f f t f s r 1 0 25 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_wait_event_type _null_ _null_ _null_ )
+insert ( 2853 pg_stat_get_backend_wait_event 11 10 12 1 0 0 0 f f f t f s r 1 0 25 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_wait_event _null_ _null_ _null_ )
+insert ( 2094 pg_stat_get_backend_activity_start 11 10 12 1 0 0 0 f f f t f s r 1 0 1184 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_activity_start _null_ _null_ _null_ )
+insert ( 2857 pg_stat_get_backend_xact_start 11 10 12 1 0 0 0 f f f t f s r 1 0 1184 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_xact_start _null_ _null_ _null_ )
+insert ( 1391 pg_stat_get_backend_start 11 10 12 1 0 0 0 f f f t f s r 1 0 1184 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_start _null_ _null_ _null_ )
+insert ( 1392 pg_stat_get_backend_client_addr 11 10 12 1 0 0 0 f f f t f s r 1 0 869 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_client_addr _null_ _null_ _null_ )
+insert ( 1393 pg_stat_get_backend_client_port 11 10 12 1 0 0 0 f f f t f s r 1 0 23 23 _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_client_port _null_ _null_ _null_ )
+insert ( 1941 pg_stat_get_db_numbackends 11 10 12 1 0 0 0 f f f t f s r 1 0 23 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_numbackends _null_ _null_ _null_ )
+insert ( 1942 pg_stat_get_db_xact_commit 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_xact_commit _null_ _null_ _null_ )
+insert ( 1943 pg_stat_get_db_xact_rollback 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_xact_rollback _null_ _null_ _null_ )
+insert ( 1944 pg_stat_get_db_blocks_fetched 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_blocks_fetched _null_ _null_ _null_ )
+insert ( 1945 pg_stat_get_db_blocks_hit 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_blocks_hit _null_ _null_ _null_ )
+insert ( 2758 pg_stat_get_db_tuples_returned 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_tuples_returned _null_ _null_ _null_ )
+insert ( 2759 pg_stat_get_db_tuples_fetched 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_tuples_fetched _null_ _null_ _null_ )
+insert ( 2760 pg_stat_get_db_tuples_inserted 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_tuples_inserted _null_ _null_ _null_ )
+insert ( 2761 pg_stat_get_db_tuples_updated 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_tuples_updated _null_ _null_ _null_ )
+insert ( 2762 pg_stat_get_db_tuples_deleted 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_tuples_deleted _null_ _null_ _null_ )
+insert ( 3065 pg_stat_get_db_conflict_tablespace 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_conflict_tablespace _null_ _null_ _null_ )
+insert ( 3066 pg_stat_get_db_conflict_lock 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_conflict_lock _null_ _null_ _null_ )
+insert ( 3067 pg_stat_get_db_conflict_snapshot 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_conflict_snapshot _null_ _null_ _null_ )
+insert ( 3068 pg_stat_get_db_conflict_bufferpin 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_conflict_bufferpin _null_ _null_ _null_ )
+insert ( 3069 pg_stat_get_db_conflict_startup_deadlock 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_conflict_startup_deadlock _null_ _null_ _null_ )
+insert ( 3070 pg_stat_get_db_conflict_all 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_conflict_all _null_ _null_ _null_ )
+insert ( 3152 pg_stat_get_db_deadlocks 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_deadlocks _null_ _null_ _null_ )
+insert ( 3426 pg_stat_get_db_checksum_failures 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_checksum_failures _null_ _null_ _null_ )
+insert ( 3428 pg_stat_get_db_checksum_last_failure 11 10 12 1 0 0 0 f f f t f s r 1 0 1184 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_checksum_last_failure _null_ _null_ _null_ )
+insert ( 3074 pg_stat_get_db_stat_reset_time 11 10 12 1 0 0 0 f f f t f s r 1 0 1184 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_stat_reset_time _null_ _null_ _null_ )
+insert ( 3150 pg_stat_get_db_temp_files 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_temp_files _null_ _null_ _null_ )
+insert ( 3151 pg_stat_get_db_temp_bytes 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_temp_bytes _null_ _null_ _null_ )
+insert ( 2844 pg_stat_get_db_blk_read_time 11 10 12 1 0 0 0 f f f t f s r 1 0 701 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_blk_read_time _null_ _null_ _null_ )
+insert ( 2845 pg_stat_get_db_blk_write_time 11 10 12 1 0 0 0 f f f t f s r 1 0 701 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_db_blk_write_time _null_ _null_ _null_ )
+insert ( 3195 pg_stat_get_archiver 11 10 12 1 0 0 0 f f f f f s r 0 0 2249 "" "{20,25,1184,20,25,1184,1184}" "{o,o,o,o,o,o,o}" "{archived_count,last_archived_wal,last_archived_time,failed_count,last_failed_wal,last_failed_time,stats_reset}" _null_ _null_ pg_stat_get_archiver _null_ _null_ _null_ )
+insert ( 2769 pg_stat_get_bgwriter_timed_checkpoints 11 10 12 1 0 0 0 f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_timed_checkpoints _null_ _null_ _null_ )
+insert ( 2770 pg_stat_get_bgwriter_requested_checkpoints 11 10 12 1 0 0 0 f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_requested_checkpoints _null_ _null_ _null_ )
+insert ( 2771 pg_stat_get_bgwriter_buf_written_checkpoints 11 10 12 1 0 0 0 f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_buf_written_checkpoints _null_ _null_ _null_ )
+insert ( 2772 pg_stat_get_bgwriter_buf_written_clean 11 10 12 1 0 0 0 f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_buf_written_clean _null_ _null_ _null_ )
+insert ( 2773 pg_stat_get_bgwriter_maxwritten_clean 11 10 12 1 0 0 0 f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_maxwritten_clean _null_ _null_ _null_ )
+insert ( 3075 pg_stat_get_bgwriter_stat_reset_time 11 10 12 1 0 0 0 f f f t f s r 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_bgwriter_stat_reset_time _null_ _null_ _null_ )
+insert ( 3160 pg_stat_get_checkpoint_write_time 11 10 12 1 0 0 0 f f f t f s r 0 0 701 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_checkpoint_write_time _null_ _null_ _null_ )
+insert ( 3161 pg_stat_get_checkpoint_sync_time 11 10 12 1 0 0 0 f f f t f s r 0 0 701 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_checkpoint_sync_time _null_ _null_ _null_ )
+insert ( 2775 pg_stat_get_buf_written_backend 11 10 12 1 0 0 0 f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_buf_written_backend _null_ _null_ _null_ )
+insert ( 3063 pg_stat_get_buf_fsync_backend 11 10 12 1 0 0 0 f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_buf_fsync_backend _null_ _null_ _null_ )
+insert ( 2859 pg_stat_get_buf_alloc 11 10 12 1 0 0 0 f f f t f s r 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_buf_alloc _null_ _null_ _null_ )
+insert ( 2306 pg_stat_get_slru 11 10 12 1 100 0 0 f f f f t s r 0 0 2249 "" "{25,20,20,20,20,20,20,20,1184}" "{o,o,o,o,o,o,o,o,o}" "{name,blks_zeroed,blks_hit,blks_read,blks_written,blks_exists,flushes,truncates,stats_reset}" _null_ _null_ pg_stat_get_slru _null_ _null_ _null_ )
+insert ( 2978 pg_stat_get_function_calls 11 10 12 1 0 0 0 f f f t f s r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_function_calls _null_ _null_ _null_ )
+insert ( 2979 pg_stat_get_function_total_time 11 10 12 1 0 0 0 f f f t f s r 1 0 701 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_function_total_time _null_ _null_ _null_ )
+insert ( 2980 pg_stat_get_function_self_time 11 10 12 1 0 0 0 f f f t f s r 1 0 701 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_function_self_time _null_ _null_ _null_ )
+insert ( 3037 pg_stat_get_xact_numscans 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_numscans _null_ _null_ _null_ )
+insert ( 3038 pg_stat_get_xact_tuples_returned 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_tuples_returned _null_ _null_ _null_ )
+insert ( 3039 pg_stat_get_xact_tuples_fetched 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_tuples_fetched _null_ _null_ _null_ )
+insert ( 3040 pg_stat_get_xact_tuples_inserted 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_tuples_inserted _null_ _null_ _null_ )
+insert ( 3041 pg_stat_get_xact_tuples_updated 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_tuples_updated _null_ _null_ _null_ )
+insert ( 3042 pg_stat_get_xact_tuples_deleted 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_tuples_deleted _null_ _null_ _null_ )
+insert ( 3043 pg_stat_get_xact_tuples_hot_updated 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_tuples_hot_updated _null_ _null_ _null_ )
+insert ( 3044 pg_stat_get_xact_blocks_fetched 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_blocks_fetched _null_ _null_ _null_ )
+insert ( 3045 pg_stat_get_xact_blocks_hit 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_blocks_hit _null_ _null_ _null_ )
+insert ( 3046 pg_stat_get_xact_function_calls 11 10 12 1 0 0 0 f f f t f v r 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_function_calls _null_ _null_ _null_ )
+insert ( 3047 pg_stat_get_xact_function_total_time 11 10 12 1 0 0 0 f f f t f v r 1 0 701 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_function_total_time _null_ _null_ _null_ )
+insert ( 3048 pg_stat_get_xact_function_self_time 11 10 12 1 0 0 0 f f f t f v r 1 0 701 26 _null_ _null_ _null_ _null_ _null_ pg_stat_get_xact_function_self_time _null_ _null_ _null_ )
+insert ( 3788 pg_stat_get_snapshot_timestamp 11 10 12 1 0 0 0 f f f t f s r 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_snapshot_timestamp _null_ _null_ _null_ )
+insert ( 2230 pg_stat_clear_snapshot 11 10 12 1 0 0 0 f f f f f v r 0 0 2278 "" _null_ _null_ _null_ _null_ _null_ pg_stat_clear_snapshot _null_ _null_ _null_ )
+insert ( 2274 pg_stat_reset 11 10 12 1 0 0 0 f f f f f v s 0 0 2278 "" _null_ _null_ _null_ _null_ _null_ pg_stat_reset _null_ _null_ _null_ )
+insert ( 3775 pg_stat_reset_shared 11 10 12 1 0 0 0 f f f t f v s 1 0 2278 25 _null_ _null_ _null_ _null_ _null_ pg_stat_reset_shared _null_ _null_ _null_ )
+insert ( 3776 pg_stat_reset_single_table_counters 11 10 12 1 0 0 0 f f f t f v s 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ pg_stat_reset_single_table_counters _null_ _null_ _null_ )
+insert ( 3777 pg_stat_reset_single_function_counters 11 10 12 1 0 0 0 f f f t f v s 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ pg_stat_reset_single_function_counters _null_ _null_ _null_ )
+insert ( 2307 pg_stat_reset_slru 11 10 12 1 0 0 0 f f f f f v s 1 0 2278 25 _null_ _null_ _null_ _null_ _null_ pg_stat_reset_slru _null_ _null_ _null_ )
+insert ( 3163 pg_trigger_depth 11 10 12 1 0 0 0 f f f t f s r 0 0 23 "" _null_ _null_ _null_ _null_ _null_ pg_trigger_depth _null_ _null_ _null_ )
+insert ( 3778 pg_tablespace_location 11 10 12 1 0 0 0 f f f t f s s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_tablespace_location _null_ _null_ _null_ )
+insert ( 1946 encode 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "17 25" _null_ _null_ _null_ _null_ _null_ binary_encode _null_ _null_ _null_ )
+insert ( 1947 decode 11 10 12 1 0 0 0 f f f t f i s 2 0 17 "25 25" _null_ _null_ _null_ _null_ _null_ binary_decode _null_ _null_ _null_ )
+insert ( 1948 byteaeq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ byteaeq _null_ _null_ _null_ )
+insert ( 1949 bytealt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ bytealt _null_ _null_ _null_ )
+insert ( 1950 byteale 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ byteale _null_ _null_ _null_ )
+insert ( 1951 byteagt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ byteagt _null_ _null_ _null_ )
+insert ( 1952 byteage 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ byteage _null_ _null_ _null_ )
+insert ( 1953 byteane 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ byteane _null_ _null_ _null_ )
+insert ( 1954 byteacmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "17 17" _null_ _null_ _null_ _null_ _null_ byteacmp _null_ _null_ _null_ )
+insert ( 3331 bytea_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ bytea_sortsupport _null_ _null_ _null_ )
+insert ( 3917 timestamp_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ timestamp_support _null_ _null_ _null_ )
+insert ( 3944 time_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ time_support _null_ _null_ _null_ )
+insert ( 1961 timestamp 11 10 12 1 0 0 3917 f f f t f i s 2 0 1114 "1114 23" _null_ _null_ _null_ _null_ _null_ timestamp_scale _null_ _null_ _null_ )
+insert ( 1965 oidlarger 11 10 12 1 0 0 0 f f f t f i s 2 0 26 "26 26" _null_ _null_ _null_ _null_ _null_ oidlarger _null_ _null_ _null_ )
+insert ( 1966 oidsmaller 11 10 12 1 0 0 0 f f f t f i s 2 0 26 "26 26" _null_ _null_ _null_ _null_ _null_ oidsmaller _null_ _null_ _null_ )
+insert ( 1967 timestamptz 11 10 12 1 0 0 3917 f f f t f i s 2 0 1184 "1184 23" _null_ _null_ _null_ _null_ _null_ timestamptz_scale _null_ _null_ _null_ )
+insert ( 1968 time 11 10 12 1 0 0 3944 f f f t f i s 2 0 1083 "1083 23" _null_ _null_ _null_ _null_ _null_ time_scale _null_ _null_ _null_ )
+insert ( 1969 timetz 11 10 12 1 0 0 3944 f f f t f i s 2 0 1266 "1266 23" _null_ _null_ _null_ _null_ _null_ timetz_scale _null_ _null_ _null_ )
+insert ( 2003 textanycat 11 10 14 1 0 0 0 f f f t f s s 2 0 25 "25 2776" _null_ _null_ _null_ _null_ _null_ "select $1 || $2::pg_catalog.text" _null_ _null_ _null_ )
+insert ( 2004 anytextcat 11 10 14 1 0 0 0 f f f t f s s 2 0 25 "2776 25" _null_ _null_ _null_ _null_ _null_ "select $1::pg_catalog.text || $2" _null_ _null_ _null_ )
+insert ( 2005 bytealike 11 10 12 1 0 0 1023 f f f t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ bytealike _null_ _null_ _null_ )
+insert ( 2006 byteanlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ byteanlike _null_ _null_ _null_ )
+insert ( 2007 like 11 10 12 1 0 0 1023 f f f t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ bytealike _null_ _null_ _null_ )
+insert ( 2008 notlike 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "17 17" _null_ _null_ _null_ _null_ _null_ byteanlike _null_ _null_ _null_ )
+insert ( 2009 like_escape 11 10 12 1 0 0 0 f f f t f i s 2 0 17 "17 17" _null_ _null_ _null_ _null_ _null_ like_escape_bytea _null_ _null_ _null_ )
+insert ( 2010 length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 17 _null_ _null_ _null_ _null_ _null_ byteaoctetlen _null_ _null_ _null_ )
+insert ( 2011 byteacat 11 10 12 1 0 0 0 f f f t f i s 2 0 17 "17 17" _null_ _null_ _null_ _null_ _null_ byteacat _null_ _null_ _null_ )
+insert ( 2012 substring 11 10 12 1 0 0 0 f f f t f i s 3 0 17 "17 23 23" _null_ _null_ _null_ _null_ _null_ bytea_substr _null_ _null_ _null_ )
+insert ( 2013 substring 11 10 12 1 0 0 0 f f f t f i s 2 0 17 "17 23" _null_ _null_ _null_ _null_ _null_ bytea_substr_no_len _null_ _null_ _null_ )
+insert ( 2085 substr 11 10 12 1 0 0 0 f f f t f i s 3 0 17 "17 23 23" _null_ _null_ _null_ _null_ _null_ bytea_substr _null_ _null_ _null_ )
+insert ( 2086 substr 11 10 12 1 0 0 0 f f f t f i s 2 0 17 "17 23" _null_ _null_ _null_ _null_ _null_ bytea_substr_no_len _null_ _null_ _null_ )
+insert ( 2014 position 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "17 17" _null_ _null_ _null_ _null_ _null_ byteapos _null_ _null_ _null_ )
+insert ( 2015 btrim 11 10 12 1 0 0 0 f f f t f i s 2 0 17 "17 17" _null_ _null_ _null_ _null_ _null_ byteatrim _null_ _null_ _null_ )
+insert ( 2019 time 11 10 12 1 0 0 0 f f f t f s s 1 0 1083 1184 _null_ _null_ _null_ _null_ _null_ timestamptz_time _null_ _null_ _null_ )
+insert ( 2020 date_trunc 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "25 1114" _null_ _null_ _null_ _null_ _null_ timestamp_trunc _null_ _null_ _null_ )
+insert ( 2021 date_part 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "25 1114" _null_ _null_ _null_ _null_ _null_ timestamp_part _null_ _null_ _null_ )
+insert ( 2024 timestamp 11 10 12 1 0 0 0 f f f t f i s 1 0 1114 1082 _null_ _null_ _null_ _null_ _null_ date_timestamp _null_ _null_ _null_ )
+insert ( 2025 timestamp 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "1082 1083" _null_ _null_ _null_ _null_ _null_ datetime_timestamp _null_ _null_ _null_ )
+insert ( 2027 timestamp 11 10 12 1 0 0 0 f f f t f s s 1 0 1114 1184 _null_ _null_ _null_ _null_ _null_ timestamptz_timestamp _null_ _null_ _null_ )
+insert ( 2028 timestamptz 11 10 12 1 0 0 0 f f f t f s s 1 0 1184 1114 _null_ _null_ _null_ _null_ _null_ timestamp_timestamptz _null_ _null_ _null_ )
+insert ( 2029 date 11 10 12 1 0 0 0 f f f t f i s 1 0 1082 1114 _null_ _null_ _null_ _null_ _null_ timestamp_date _null_ _null_ _null_ )
+insert ( 2031 timestamp_mi 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_mi _null_ _null_ _null_ )
+insert ( 2032 timestamp_pl_interval 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "1114 1186" _null_ _null_ _null_ _null_ _null_ timestamp_pl_interval _null_ _null_ _null_ )
+insert ( 2033 timestamp_mi_interval 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "1114 1186" _null_ _null_ _null_ _null_ _null_ timestamp_mi_interval _null_ _null_ _null_ )
+insert ( 2035 timestamp_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_smaller _null_ _null_ _null_ )
+insert ( 2036 timestamp_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_larger _null_ _null_ _null_ )
+insert ( 2037 timezone 11 10 12 1 0 0 0 f f f t f v s 2 0 1266 "25 1266" _null_ _null_ _null_ _null_ _null_ timetz_zone _null_ _null_ _null_ )
+insert ( 2038 timezone 11 10 12 1 0 0 0 f f f t f i s 2 0 1266 "1186 1266" _null_ _null_ _null_ _null_ _null_ timetz_izone _null_ _null_ _null_ )
+insert ( 2039 timestamp_hash 11 10 12 1 0 0 0 f f f t f i s 1 0 23 1114 _null_ _null_ _null_ _null_ _null_ timestamp_hash _null_ _null_ _null_ )
+insert ( 3411 timestamp_hash_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "1114 20" _null_ _null_ _null_ _null_ _null_ timestamp_hash_extended _null_ _null_ _null_ )
+insert ( 2041 overlaps 11 10 12 1 0 0 0 f f f f f i s 4 0 16 "1114 1114 1114 1114" _null_ _null_ _null_ _null_ _null_ overlaps_timestamp _null_ _null_ _null_ )
+insert ( 2042 overlaps 11 10 14 1 0 0 0 f f f f f i s 4 0 16 "1114 1186 1114 1186" _null_ _null_ _null_ _null_ _null_ "select ($1, ($1 + $2)) overlaps ($3, ($3 + $4))" _null_ _null_ _null_ )
+insert ( 2043 overlaps 11 10 14 1 0 0 0 f f f f f i s 4 0 16 "1114 1114 1114 1186" _null_ _null_ _null_ _null_ _null_ "select ($1, $2) overlaps ($3, ($3 + $4))" _null_ _null_ _null_ )
+insert ( 2044 overlaps 11 10 14 1 0 0 0 f f f f f i s 4 0 16 "1114 1186 1114 1114" _null_ _null_ _null_ _null_ _null_ "select ($1, ($1 + $2)) overlaps ($3, $4)" _null_ _null_ _null_ )
+insert ( 2045 timestamp_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_cmp _null_ _null_ _null_ )
+insert ( 3137 timestamp_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ timestamp_sortsupport _null_ _null_ _null_ )
+insert ( 4134 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "1114 1114 1186 16 16" _null_ _null_ _null_ _null_ _null_ in_range_timestamp_interval _null_ _null_ _null_ )
+insert ( 4135 in_range 11 10 12 1 0 0 0 f f f t f s s 5 0 16 "1184 1184 1186 16 16" _null_ _null_ _null_ _null_ _null_ in_range_timestamptz_interval _null_ _null_ _null_ )
+insert ( 4136 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "1186 1186 1186 16 16" _null_ _null_ _null_ _null_ _null_ in_range_interval_interval _null_ _null_ _null_ )
+insert ( 4137 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "1083 1083 1186 16 16" _null_ _null_ _null_ _null_ _null_ in_range_time_interval _null_ _null_ _null_ )
+insert ( 4138 in_range 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "1266 1266 1186 16 16" _null_ _null_ _null_ _null_ _null_ in_range_timetz_interval _null_ _null_ _null_ )
+insert ( 2046 time 11 10 12 1 0 0 0 f f f t f i s 1 0 1083 1266 _null_ _null_ _null_ _null_ _null_ timetz_time _null_ _null_ _null_ )
+insert ( 2047 timetz 11 10 12 1 0 0 0 f f f t f s s 1 0 1266 1083 _null_ _null_ _null_ _null_ _null_ time_timetz _null_ _null_ _null_ )
+insert ( 2048 isfinite 11 10 12 1 0 0 0 f f f t f i s 1 0 16 1114 _null_ _null_ _null_ _null_ _null_ timestamp_finite _null_ _null_ _null_ )
+insert ( 2049 to_char 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "1114 25" _null_ _null_ _null_ _null_ _null_ timestamp_to_char _null_ _null_ _null_ )
+insert ( 2052 timestamp_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_eq _null_ _null_ _null_ )
+insert ( 2053 timestamp_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_ne _null_ _null_ _null_ )
+insert ( 2054 timestamp_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_lt _null_ _null_ _null_ )
+insert ( 2055 timestamp_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_le _null_ _null_ _null_ )
+insert ( 2056 timestamp_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_ge _null_ _null_ _null_ )
+insert ( 2057 timestamp_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_gt _null_ _null_ _null_ )
+insert ( 2058 age 11 10 12 1 0 0 0 f f f t f i s 2 0 1186 "1114 1114" _null_ _null_ _null_ _null_ _null_ timestamp_age _null_ _null_ _null_ )
+insert ( 2059 age 11 10 14 1 0 0 0 f f f t f s s 1 0 1186 1114 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.age(cast(current_date as timestamp without time zone), $1)" _null_ _null_ _null_ )
+insert ( 2069 timezone 11 10 12 1 0 0 0 f f f t f i s 2 0 1184 "25 1114" _null_ _null_ _null_ _null_ _null_ timestamp_zone _null_ _null_ _null_ )
+insert ( 2070 timezone 11 10 12 1 0 0 0 f f f t f i s 2 0 1184 "1186 1114" _null_ _null_ _null_ _null_ _null_ timestamp_izone _null_ _null_ _null_ )
+insert ( 2071 date_pl_interval 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "1082 1186" _null_ _null_ _null_ _null_ _null_ date_pl_interval _null_ _null_ _null_ )
+insert ( 2072 date_mi_interval 11 10 12 1 0 0 0 f f f t f i s 2 0 1114 "1082 1186" _null_ _null_ _null_ _null_ _null_ date_mi_interval _null_ _null_ _null_ )
+insert ( 2073 substring 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ textregexsubstr _null_ _null_ _null_ )
+insert ( 2074 substring 11 10 14 1 0 0 0 f f f t f i s 3 0 25 "25 25 25" _null_ _null_ _null_ _null_ _null_ "select pg_catalog.substring($1, pg_catalog.similar_to_escape($2, $3))" _null_ _null_ _null_ )
+insert ( 2075 bit 11 10 12 1 0 0 0 f f f t f i s 2 0 1560 "20 23" _null_ _null_ _null_ _null_ _null_ bitfromint8 _null_ _null_ _null_ )
+insert ( 2076 int8 11 10 12 1 0 0 0 f f f t f i s 1 0 20 1560 _null_ _null_ _null_ _null_ _null_ bittoint8 _null_ _null_ _null_ )
+insert ( 2077 current_setting 11 10 12 1 0 0 0 f f f t f s s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ show_config_by_name _null_ _null_ _null_ )
+insert ( 3294 current_setting 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "25 16" _null_ _null_ _null_ _null_ _null_ show_config_by_name_missing_ok _null_ _null_ _null_ )
+insert ( 2078 set_config 11 10 12 1 0 0 0 f f f f f v u 3 0 25 "25 25 16" _null_ _null_ _null_ _null_ _null_ set_config_by_name _null_ _null_ _null_ )
+insert ( 2084 pg_show_all_settings 11 10 12 1 1000 0 0 f f f t t s s 0 0 2249 "" "{25,25,25,25,25,25,25,25,25,25,25,1009,25,25,25,23,16}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline,pending_restart}" _null_ _null_ show_all_settings _null_ _null_ _null_ )
+insert ( 3329 pg_show_all_file_settings 11 10 12 1 1000 0 0 f f f t t v s 0 0 2249 "" "{25,23,23,25,25,16,25}" "{o,o,o,o,o,o,o}" "{sourcefile,sourceline,seqno,name,setting,applied,error}" _null_ _null_ show_all_file_settings _null_ _null_ _null_ )
+insert ( 3401 pg_hba_file_rules 11 10 12 1 1000 0 0 f f f t t v s 0 0 2249 "" "{23,25,1009,1009,25,25,25,1009,25}" "{o,o,o,o,o,o,o,o,o}" "{line_number,type,database,user_name,address,netmask,auth_method,options,error}" _null_ _null_ pg_hba_file_rules _null_ _null_ _null_ )
+insert ( 1371 pg_lock_status 11 10 12 1 1000 0 0 f f f t t v s 0 0 2249 "" "{25,26,26,23,21,25,28,26,26,21,25,23,25,16,16}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid,virtualtransaction,pid,mode,granted,fastpath}" _null_ _null_ pg_lock_status _null_ _null_ _null_ )
+insert ( 2561 pg_blocking_pids 11 10 12 1 0 0 0 f f f t f v s 1 0 1007 23 _null_ _null_ _null_ _null_ _null_ pg_blocking_pids _null_ _null_ _null_ )
+insert ( 3376 pg_safe_snapshot_blocking_pids 11 10 12 1 0 0 0 f f f t f v s 1 0 1007 23 _null_ _null_ _null_ _null_ _null_ pg_safe_snapshot_blocking_pids _null_ _null_ _null_ )
+insert ( 3378 pg_isolation_test_session_is_blocked 11 10 12 1 0 0 0 f f f t f v s 2 0 16 "23 1007" _null_ _null_ _null_ _null_ _null_ pg_isolation_test_session_is_blocked _null_ _null_ _null_ )
+insert ( 1065 pg_prepared_xact 11 10 12 1 1000 0 0 f f f t t v s 0 0 2249 "" "{28,25,1184,26,26}" "{o,o,o,o,o}" "{transaction,gid,prepared,ownerid,dbid}" _null_ _null_ pg_prepared_xact _null_ _null_ _null_ )
+insert ( 3819 pg_get_multixact_members 11 10 12 1 1000 0 0 f f f t t v s 1 0 2249 28 "{28,28,25}" "{i,o,o}" "{multixid,xid,mode}" _null_ _null_ pg_get_multixact_members _null_ _null_ _null_ )
+insert ( 3581 pg_xact_commit_timestamp 11 10 12 1 0 0 0 f f f t f v s 1 0 1184 28 _null_ _null_ _null_ _null_ _null_ pg_xact_commit_timestamp _null_ _null_ _null_ )
+insert ( 3583 pg_last_committed_xact 11 10 12 1 0 0 0 f f f t f v s 0 0 2249 "" "{28,1184}" "{o,o}" "{xid,timestamp}" _null_ _null_ pg_last_committed_xact _null_ _null_ _null_ )
+insert ( 3537 pg_describe_object 11 10 12 1 0 0 0 f f f t f s s 3 0 25 "26 26 23" _null_ _null_ _null_ _null_ _null_ pg_describe_object _null_ _null_ _null_ )
+insert ( 3839 pg_identify_object 11 10 12 1 0 0 0 f f f t f s s 3 0 2249 "26 26 23" "{26,26,23,25,25,25,25}" "{i,i,i,o,o,o,o}" "{classid,objid,objsubid,type,schema,name,identity}" _null_ _null_ pg_identify_object _null_ _null_ _null_ )
+insert ( 3382 pg_identify_object_as_address 11 10 12 1 0 0 0 f f f t f s s 3 0 2249 "26 26 23" "{26,26,23,25,1009,1009}" "{i,i,i,o,o,o}" "{classid,objid,objsubid,type,object_names,object_args}" _null_ _null_ pg_identify_object_as_address _null_ _null_ _null_ )
+insert ( 3954 pg_get_object_address 11 10 12 1 0 0 0 f f f t f s s 3 0 2249 "25 1009 1009" "{25,1009,1009,26,26,23}" "{i,i,i,o,o,o}" "{type,object_names,object_args,classid,objid,objsubid}" _null_ _null_ pg_get_object_address _null_ _null_ _null_ )
+insert ( 2079 pg_table_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_table_is_visible _null_ _null_ _null_ )
+insert ( 2080 pg_type_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_type_is_visible _null_ _null_ _null_ )
+insert ( 2081 pg_function_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_function_is_visible _null_ _null_ _null_ )
+insert ( 2082 pg_operator_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_operator_is_visible _null_ _null_ _null_ )
+insert ( 2083 pg_opclass_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_opclass_is_visible _null_ _null_ _null_ )
+insert ( 3829 pg_opfamily_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_opfamily_is_visible _null_ _null_ _null_ )
+insert ( 2093 pg_conversion_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_conversion_is_visible _null_ _null_ _null_ )
+insert ( 3403 pg_statistics_obj_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_statistics_obj_is_visible _null_ _null_ _null_ )
+insert ( 3756 pg_ts_parser_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_ts_parser_is_visible _null_ _null_ _null_ )
+insert ( 3757 pg_ts_dict_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_ts_dict_is_visible _null_ _null_ _null_ )
+insert ( 3768 pg_ts_template_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_ts_template_is_visible _null_ _null_ _null_ )
+insert ( 3758 pg_ts_config_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_ts_config_is_visible _null_ _null_ _null_ )
+insert ( 3815 pg_collation_is_visible 11 10 12 10 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_collation_is_visible _null_ _null_ _null_ )
+insert ( 2854 pg_my_temp_schema 11 10 12 1 0 0 0 f f f t f s r 0 0 26 "" _null_ _null_ _null_ _null_ _null_ pg_my_temp_schema _null_ _null_ _null_ )
+insert ( 2855 pg_is_other_temp_schema 11 10 12 1 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ pg_is_other_temp_schema _null_ _null_ _null_ )
+insert ( 2171 pg_cancel_backend 11 10 12 1 0 0 0 f f f t f v s 1 0 16 23 _null_ _null_ _null_ _null_ _null_ pg_cancel_backend _null_ _null_ _null_ )
+insert ( 2096 pg_terminate_backend 11 10 12 1 0 0 0 f f f t f v s 1 0 16 23 _null_ _null_ _null_ _null_ _null_ pg_terminate_backend _null_ _null_ _null_ )
+insert ( 2172 pg_start_backup 11 10 12 1 0 0 0 f f f t f v r 3 0 3220 "25 16 16" _null_ _null_ _null_ _null_ _null_ pg_start_backup _null_ _null_ _null_ )
+insert ( 2173 pg_stop_backup 11 10 12 1 0 0 0 f f f t f v r 0 0 3220 "" _null_ _null_ _null_ _null_ _null_ pg_stop_backup _null_ _null_ _null_ )
+insert ( 2739 pg_stop_backup 11 10 12 1 1 0 0 f f f t t v r 2 0 2249 "16 16" "{16,16,3220,25,25}" "{i,i,o,o,o}" "{exclusive,wait_for_archive,lsn,labelfile,spcmapfile}" _null_ _null_ pg_stop_backup_v2 _null_ _null_ _null_ )
+insert ( 3813 pg_is_in_backup 11 10 12 1 0 0 0 f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_is_in_backup _null_ _null_ _null_ )
+insert ( 3814 pg_backup_start_time 11 10 12 1 0 0 0 f f f t f s s 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ pg_backup_start_time _null_ _null_ _null_ )
+insert ( 3436 pg_promote 11 10 12 1 0 0 0 f f f t f v s 2 0 16 "16 23" _null_ _null_ "{wait,wait_seconds}" _null_ _null_ pg_promote _null_ _null_ _null_ )
+insert ( 2848 pg_switch_wal 11 10 12 1 0 0 0 f f f t f v s 0 0 3220 "" _null_ _null_ _null_ _null_ _null_ pg_switch_wal _null_ _null_ _null_ )
+insert ( 3098 pg_create_restore_point 11 10 12 1 0 0 0 f f f t f v s 1 0 3220 25 _null_ _null_ _null_ _null_ _null_ pg_create_restore_point _null_ _null_ _null_ )
+insert ( 2849 pg_current_wal_lsn 11 10 12 1 0 0 0 f f f t f v s 0 0 3220 "" _null_ _null_ _null_ _null_ _null_ pg_current_wal_lsn _null_ _null_ _null_ )
+insert ( 2852 pg_current_wal_insert_lsn 11 10 12 1 0 0 0 f f f t f v s 0 0 3220 "" _null_ _null_ _null_ _null_ _null_ pg_current_wal_insert_lsn _null_ _null_ _null_ )
+insert ( 3330 pg_current_wal_flush_lsn 11 10 12 1 0 0 0 f f f t f v s 0 0 3220 "" _null_ _null_ _null_ _null_ _null_ pg_current_wal_flush_lsn _null_ _null_ _null_ )
+insert ( 2850 pg_walfile_name_offset 11 10 12 1 0 0 0 f f f t f i s 1 0 2249 3220 "{3220,25,23}" "{i,o,o}" "{lsn,file_name,file_offset}" _null_ _null_ pg_walfile_name_offset _null_ _null_ _null_ )
+insert ( 2851 pg_walfile_name 11 10 12 1 0 0 0 f f f t f i s 1 0 25 3220 _null_ _null_ _null_ _null_ _null_ pg_walfile_name _null_ _null_ _null_ )
+insert ( 3165 pg_wal_lsn_diff 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_wal_lsn_diff _null_ _null_ _null_ )
+insert ( 3809 pg_export_snapshot 11 10 12 1 0 0 0 f f f t f v u 0 0 25 "" _null_ _null_ _null_ _null_ _null_ pg_export_snapshot _null_ _null_ _null_ )
+insert ( 3810 pg_is_in_recovery 11 10 12 1 0 0 0 f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_is_in_recovery _null_ _null_ _null_ )
+insert ( 3820 pg_last_wal_receive_lsn 11 10 12 1 0 0 0 f f f t f v s 0 0 3220 "" _null_ _null_ _null_ _null_ _null_ pg_last_wal_receive_lsn _null_ _null_ _null_ )
+insert ( 3821 pg_last_wal_replay_lsn 11 10 12 1 0 0 0 f f f t f v s 0 0 3220 "" _null_ _null_ _null_ _null_ _null_ pg_last_wal_replay_lsn _null_ _null_ _null_ )
+insert ( 3830 pg_last_xact_replay_timestamp 11 10 12 1 0 0 0 f f f t f v s 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ pg_last_xact_replay_timestamp _null_ _null_ _null_ )
+insert ( 3071 pg_wal_replay_pause 11 10 12 1 0 0 0 f f f t f v s 0 0 2278 "" _null_ _null_ _null_ _null_ _null_ pg_wal_replay_pause _null_ _null_ _null_ )
+insert ( 3072 pg_wal_replay_resume 11 10 12 1 0 0 0 f f f t f v s 0 0 2278 "" _null_ _null_ _null_ _null_ _null_ pg_wal_replay_resume _null_ _null_ _null_ )
+insert ( 3073 pg_is_wal_replay_paused 11 10 12 1 0 0 0 f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_is_wal_replay_paused _null_ _null_ _null_ )
+insert ( 2621 pg_reload_conf 11 10 12 1 0 0 0 f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_reload_conf _null_ _null_ _null_ )
+insert ( 2622 pg_rotate_logfile 11 10 12 1 0 0 0 f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_rotate_logfile_v2 _null_ _null_ _null_ )
+insert ( 4099 pg_rotate_logfile_old 11 10 12 1 0 0 0 f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_rotate_logfile _null_ _null_ _null_ )
+insert ( 3800 pg_current_logfile 11 10 12 1 0 0 0 f f f f f v s 0 0 25 "" _null_ _null_ _null_ _null_ _null_ pg_current_logfile _null_ _null_ _null_ )
+insert ( 3801 pg_current_logfile 11 10 12 1 0 0 0 f f f f f v s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ pg_current_logfile_1arg _null_ _null_ _null_ )
+insert ( 2623 pg_stat_file 11 10 12 1 0 0 0 f f f t f v s 1 0 2249 25 "{25,20,1184,1184,1184,1184,16}" "{i,o,o,o,o,o,o}" "{filename,size,access,modification,change,creation,isdir}" _null_ _null_ pg_stat_file_1arg _null_ _null_ _null_ )
+insert ( 3307 pg_stat_file 11 10 12 1 0 0 0 f f f t f v s 2 0 2249 "25 16" "{25,16,20,1184,1184,1184,1184,16}" "{i,i,o,o,o,o,o,o}" "{filename,missing_ok,size,access,modification,change,creation,isdir}" _null_ _null_ pg_stat_file _null_ _null_ _null_ )
+insert ( 2624 pg_read_file 11 10 12 1 0 0 0 f f f t f v s 3 0 25 "25 20 20" _null_ _null_ _null_ _null_ _null_ pg_read_file_off_len _null_ _null_ _null_ )
+insert ( 3293 pg_read_file 11 10 12 1 0 0 0 f f f t f v s 4 0 25 "25 20 20 16" _null_ _null_ _null_ _null_ _null_ pg_read_file_v2 _null_ _null_ _null_ )
+insert ( 4100 pg_read_file_old 11 10 12 1 0 0 0 f f f t f v s 3 0 25 "25 20 20" _null_ _null_ _null_ _null_ _null_ pg_read_file _null_ _null_ _null_ )
+insert ( 3826 pg_read_file 11 10 12 1 0 0 0 f f f t f v s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ pg_read_file_all _null_ _null_ _null_ )
+insert ( 3827 pg_read_binary_file 11 10 12 1 0 0 0 f f f t f v s 3 0 17 "25 20 20" _null_ _null_ _null_ _null_ _null_ pg_read_binary_file_off_len _null_ _null_ _null_ )
+insert ( 3295 pg_read_binary_file 11 10 12 1 0 0 0 f f f t f v s 4 0 17 "25 20 20 16" _null_ _null_ _null_ _null_ _null_ pg_read_binary_file _null_ _null_ _null_ )
+insert ( 3828 pg_read_binary_file 11 10 12 1 0 0 0 f f f t f v s 1 0 17 25 _null_ _null_ _null_ _null_ _null_ pg_read_binary_file_all _null_ _null_ _null_ )
+insert ( 2625 pg_ls_dir 11 10 12 1 1000 0 0 f f f t t v s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ pg_ls_dir_1arg _null_ _null_ _null_ )
+insert ( 3297 pg_ls_dir 11 10 12 1 1000 0 0 f f f t t v s 3 0 25 "25 16 16" _null_ _null_ _null_ _null_ _null_ pg_ls_dir _null_ _null_ _null_ )
+insert ( 2626 pg_sleep 11 10 12 1 0 0 0 f f f t f v s 1 0 2278 701 _null_ _null_ _null_ _null_ _null_ pg_sleep _null_ _null_ _null_ )
+insert ( 3935 pg_sleep_for 11 10 14 1 0 0 0 f f f t f v s 1 0 2278 1186 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.pg_sleep(extract(epoch from pg_catalog.clock_timestamp() operator(pg_catalog.+) $1) operator(pg_catalog.-) extract(epoch from pg_catalog.clock_timestamp()))" _null_ _null_ _null_ )
+insert ( 3936 pg_sleep_until 11 10 14 1 0 0 0 f f f t f v s 1 0 2278 1184 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.pg_sleep(extract(epoch from $1) operator(pg_catalog.-) extract(epoch from pg_catalog.clock_timestamp()))" _null_ _null_ _null_ )
+insert ( 315 pg_jit_available 11 10 12 1 0 0 0 f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_jit_available _null_ _null_ _null_ )
+insert ( 2971 text 11 10 12 1 0 0 0 f f f t f i s 1 0 25 16 _null_ _null_ _null_ _null_ _null_ booltext _null_ _null_ _null_ )
+insert ( 2100 avg 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2101 avg 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2102 avg 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2103 avg 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2104 avg 11 10 12 1 0 0 0 a f f f f i s 1 0 701 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2105 avg 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2106 avg 11 10 12 1 0 0 0 a f f f f i s 1 0 1186 1186 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2107 sum 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2108 sum 11 10 12 1 0 0 0 a f f f f i s 1 0 20 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2109 sum 11 10 12 1 0 0 0 a f f f f i s 1 0 20 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2110 sum 11 10 12 1 0 0 0 a f f f f i s 1 0 700 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2111 sum 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2112 sum 11 10 12 1 0 0 0 a f f f f i s 1 0 790 790 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2113 sum 11 10 12 1 0 0 0 a f f f f i s 1 0 1186 1186 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2114 sum 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2115 max 11 10 12 1 0 0 0 a f f f f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2116 max 11 10 12 1 0 0 0 a f f f f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2117 max 11 10 12 1 0 0 0 a f f f f i s 1 0 21 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2118 max 11 10 12 1 0 0 0 a f f f f i s 1 0 26 26 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2119 max 11 10 12 1 0 0 0 a f f f f i s 1 0 700 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2120 max 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2122 max 11 10 12 1 0 0 0 a f f f f i s 1 0 1082 1082 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2123 max 11 10 12 1 0 0 0 a f f f f i s 1 0 1083 1083 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2124 max 11 10 12 1 0 0 0 a f f f f i s 1 0 1266 1266 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2125 max 11 10 12 1 0 0 0 a f f f f i s 1 0 790 790 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2126 max 11 10 12 1 0 0 0 a f f f f i s 1 0 1114 1114 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2127 max 11 10 12 1 0 0 0 a f f f f i s 1 0 1184 1184 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2128 max 11 10 12 1 0 0 0 a f f f f i s 1 0 1186 1186 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2129 max 11 10 12 1 0 0 0 a f f f f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2130 max 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2050 max 11 10 12 1 0 0 0 a f f f f i s 1 0 2277 2277 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2244 max 11 10 12 1 0 0 0 a f f f f i s 1 0 1042 1042 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2797 max 11 10 12 1 0 0 0 a f f f f i s 1 0 27 27 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3564 max 11 10 12 1 0 0 0 a f f f f i s 1 0 869 869 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 4189 max 11 10 12 1 0 0 0 a f f f f i s 1 0 3220 3220 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2131 min 11 10 12 1 0 0 0 a f f f f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2132 min 11 10 12 1 0 0 0 a f f f f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2133 min 11 10 12 1 0 0 0 a f f f f i s 1 0 21 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2134 min 11 10 12 1 0 0 0 a f f f f i s 1 0 26 26 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2135 min 11 10 12 1 0 0 0 a f f f f i s 1 0 700 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2136 min 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2138 min 11 10 12 1 0 0 0 a f f f f i s 1 0 1082 1082 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2139 min 11 10 12 1 0 0 0 a f f f f i s 1 0 1083 1083 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2140 min 11 10 12 1 0 0 0 a f f f f i s 1 0 1266 1266 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2141 min 11 10 12 1 0 0 0 a f f f f i s 1 0 790 790 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2142 min 11 10 12 1 0 0 0 a f f f f i s 1 0 1114 1114 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2143 min 11 10 12 1 0 0 0 a f f f f i s 1 0 1184 1184 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2144 min 11 10 12 1 0 0 0 a f f f f i s 1 0 1186 1186 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2145 min 11 10 12 1 0 0 0 a f f f f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2146 min 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2051 min 11 10 12 1 0 0 0 a f f f f i s 1 0 2277 2277 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2245 min 11 10 12 1 0 0 0 a f f f f i s 1 0 1042 1042 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2798 min 11 10 12 1 0 0 0 a f f f f i s 1 0 27 27 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3565 min 11 10 12 1 0 0 0 a f f f f i s 1 0 869 869 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 4190 min 11 10 12 1 0 0 0 a f f f f i s 1 0 3220 3220 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2147 count 11 10 12 1 0 0 0 a f f f f i s 1 0 20 2276 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2803 count 11 10 12 1 0 0 0 a f f f f i s 0 0 20 "" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2718 var_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2719 var_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2720 var_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2721 var_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 701 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2722 var_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2723 var_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2641 var_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2642 var_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2643 var_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2644 var_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 701 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2645 var_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2646 var_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2148 variance 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2149 variance 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2150 variance 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2151 variance 11 10 12 1 0 0 0 a f f f f i s 1 0 701 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2152 variance 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2153 variance 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2724 stddev_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2725 stddev_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2726 stddev_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2727 stddev_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 701 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2728 stddev_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2729 stddev_pop 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2712 stddev_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2713 stddev_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2714 stddev_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2715 stddev_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 701 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2716 stddev_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2717 stddev_samp 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2154 stddev 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2155 stddev 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2156 stddev 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2157 stddev 11 10 12 1 0 0 0 a f f f f i s 1 0 701 700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2158 stddev 11 10 12 1 0 0 0 a f f f f i s 1 0 701 701 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2159 stddev 11 10 12 1 0 0 0 a f f f f i s 1 0 1700 1700 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2818 regr_count 11 10 12 1 0 0 0 a f f f f i s 2 0 20 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2819 regr_sxx 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2820 regr_syy 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2821 regr_sxy 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2822 regr_avgx 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2823 regr_avgy 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2824 regr_r2 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2825 regr_slope 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2826 regr_intercept 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2827 covar_pop 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2828 covar_samp 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2829 corr 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2160 text_pattern_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ text_pattern_lt _null_ _null_ _null_ )
+insert ( 2161 text_pattern_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ text_pattern_le _null_ _null_ _null_ )
+insert ( 2163 text_pattern_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ text_pattern_ge _null_ _null_ _null_ )
+insert ( 2164 text_pattern_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ text_pattern_gt _null_ _null_ _null_ )
+insert ( 2166 bttext_pattern_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "25 25" _null_ _null_ _null_ _null_ _null_ bttext_pattern_cmp _null_ _null_ _null_ )
+insert ( 3332 bttext_pattern_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ bttext_pattern_sortsupport _null_ _null_ _null_ )
+insert ( 2174 bpchar_pattern_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpchar_pattern_lt _null_ _null_ _null_ )
+insert ( 2175 bpchar_pattern_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpchar_pattern_le _null_ _null_ _null_ )
+insert ( 2177 bpchar_pattern_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpchar_pattern_ge _null_ _null_ _null_ )
+insert ( 2178 bpchar_pattern_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "1042 1042" _null_ _null_ _null_ _null_ _null_ bpchar_pattern_gt _null_ _null_ _null_ )
+insert ( 2180 btbpchar_pattern_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "1042 1042" _null_ _null_ _null_ _null_ _null_ btbpchar_pattern_cmp _null_ _null_ _null_ )
+insert ( 3333 btbpchar_pattern_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ btbpchar_pattern_sortsupport _null_ _null_ _null_ )
+insert ( 2188 btint48cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "23 20" _null_ _null_ _null_ _null_ _null_ btint48cmp _null_ _null_ _null_ )
+insert ( 2189 btint84cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "20 23" _null_ _null_ _null_ _null_ _null_ btint84cmp _null_ _null_ _null_ )
+insert ( 2190 btint24cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "21 23" _null_ _null_ _null_ _null_ _null_ btint24cmp _null_ _null_ _null_ )
+insert ( 2191 btint42cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "23 21" _null_ _null_ _null_ _null_ _null_ btint42cmp _null_ _null_ _null_ )
+insert ( 2192 btint28cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "21 20" _null_ _null_ _null_ _null_ _null_ btint28cmp _null_ _null_ _null_ )
+insert ( 2193 btint82cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "20 21" _null_ _null_ _null_ _null_ _null_ btint82cmp _null_ _null_ _null_ )
+insert ( 2194 btfloat48cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "700 701" _null_ _null_ _null_ _null_ _null_ btfloat48cmp _null_ _null_ _null_ )
+insert ( 2195 btfloat84cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "701 700" _null_ _null_ _null_ _null_ _null_ btfloat84cmp _null_ _null_ _null_ )
+insert ( 2212 regprocedurein 11 10 12 1 0 0 0 f f f t f s s 1 0 2202 2275 _null_ _null_ _null_ _null_ _null_ regprocedurein _null_ _null_ _null_ )
+insert ( 2213 regprocedureout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 2202 _null_ _null_ _null_ _null_ _null_ regprocedureout _null_ _null_ _null_ )
+insert ( 2214 regoperin 11 10 12 1 0 0 0 f f f t f s s 1 0 2203 2275 _null_ _null_ _null_ _null_ _null_ regoperin _null_ _null_ _null_ )
+insert ( 2215 regoperout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 2203 _null_ _null_ _null_ _null_ _null_ regoperout _null_ _null_ _null_ )
+insert ( 3492 to_regoper 11 10 12 1 0 0 0 f f f t f s s 1 0 2203 25 _null_ _null_ _null_ _null_ _null_ to_regoper _null_ _null_ _null_ )
+insert ( 3476 to_regoperator 11 10 12 1 0 0 0 f f f t f s s 1 0 2204 25 _null_ _null_ _null_ _null_ _null_ to_regoperator _null_ _null_ _null_ )
+insert ( 2216 regoperatorin 11 10 12 1 0 0 0 f f f t f s s 1 0 2204 2275 _null_ _null_ _null_ _null_ _null_ regoperatorin _null_ _null_ _null_ )
+insert ( 2217 regoperatorout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 2204 _null_ _null_ _null_ _null_ _null_ regoperatorout _null_ _null_ _null_ )
+insert ( 2218 regclassin 11 10 12 1 0 0 0 f f f t f s s 1 0 2205 2275 _null_ _null_ _null_ _null_ _null_ regclassin _null_ _null_ _null_ )
+insert ( 2219 regclassout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 2205 _null_ _null_ _null_ _null_ _null_ regclassout _null_ _null_ _null_ )
+insert ( 3495 to_regclass 11 10 12 1 0 0 0 f f f t f s s 1 0 2205 25 _null_ _null_ _null_ _null_ _null_ to_regclass _null_ _null_ _null_ )
+insert ( 4193 regcollationin 11 10 12 1 0 0 0 f f f t f s s 1 0 4191 2275 _null_ _null_ _null_ _null_ _null_ regcollationin _null_ _null_ _null_ )
+insert ( 4194 regcollationout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 4191 _null_ _null_ _null_ _null_ _null_ regcollationout _null_ _null_ _null_ )
+insert ( 4195 to_regcollation 11 10 12 1 0 0 0 f f f t f s s 1 0 4191 25 _null_ _null_ _null_ _null_ _null_ to_regcollation _null_ _null_ _null_ )
+insert ( 2220 regtypein 11 10 12 1 0 0 0 f f f t f s s 1 0 2206 2275 _null_ _null_ _null_ _null_ _null_ regtypein _null_ _null_ _null_ )
+insert ( 2221 regtypeout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 2206 _null_ _null_ _null_ _null_ _null_ regtypeout _null_ _null_ _null_ )
+insert ( 3493 to_regtype 11 10 12 1 0 0 0 f f f t f s s 1 0 2206 25 _null_ _null_ _null_ _null_ _null_ to_regtype _null_ _null_ _null_ )
+insert ( 1079 regclass 11 10 12 1 0 0 0 f f f t f s s 1 0 2205 25 _null_ _null_ _null_ _null_ _null_ text_regclass _null_ _null_ _null_ )
+insert ( 4098 regrolein 11 10 12 1 0 0 0 f f f t f s s 1 0 4096 2275 _null_ _null_ _null_ _null_ _null_ regrolein _null_ _null_ _null_ )
+insert ( 4092 regroleout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 4096 _null_ _null_ _null_ _null_ _null_ regroleout _null_ _null_ _null_ )
+insert ( 4093 to_regrole 11 10 12 1 0 0 0 f f f t f s s 1 0 4096 25 _null_ _null_ _null_ _null_ _null_ to_regrole _null_ _null_ _null_ )
+insert ( 4084 regnamespacein 11 10 12 1 0 0 0 f f f t f s s 1 0 4089 2275 _null_ _null_ _null_ _null_ _null_ regnamespacein _null_ _null_ _null_ )
+insert ( 4085 regnamespaceout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 4089 _null_ _null_ _null_ _null_ _null_ regnamespaceout _null_ _null_ _null_ )
+insert ( 4086 to_regnamespace 11 10 12 1 0 0 0 f f f t f s s 1 0 4089 25 _null_ _null_ _null_ _null_ _null_ to_regnamespace _null_ _null_ _null_ )
+insert ( 1268 parse_ident 11 10 12 1 0 0 0 f f f t f i s 2 0 1009 "25 16" _null_ _null_ "{str,strict}" _null_ _null_ parse_ident _null_ _null_ _null_ )
+insert ( 2246 fmgr_internal_validator 11 10 12 1 0 0 0 f f f t f s s 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ fmgr_internal_validator _null_ _null_ _null_ )
+insert ( 2247 fmgr_c_validator 11 10 12 1 0 0 0 f f f t f s s 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ fmgr_c_validator _null_ _null_ _null_ )
+insert ( 2248 fmgr_sql_validator 11 10 12 1 0 0 0 f f f t f s s 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ fmgr_sql_validator _null_ _null_ _null_ )
+insert ( 2250 has_database_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_database_privilege_name_name _null_ _null_ _null_ )
+insert ( 2251 has_database_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_database_privilege_name_id _null_ _null_ _null_ )
+insert ( 2252 has_database_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_database_privilege_id_name _null_ _null_ _null_ )
+insert ( 2253 has_database_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_database_privilege_id_id _null_ _null_ _null_ )
+insert ( 2254 has_database_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_database_privilege_name _null_ _null_ _null_ )
+insert ( 2255 has_database_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_database_privilege_id _null_ _null_ _null_ )
+insert ( 2256 has_function_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_function_privilege_name_name _null_ _null_ _null_ )
+insert ( 2257 has_function_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_function_privilege_name_id _null_ _null_ _null_ )
+insert ( 2258 has_function_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_function_privilege_id_name _null_ _null_ _null_ )
+insert ( 2259 has_function_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_function_privilege_id_id _null_ _null_ _null_ )
+insert ( 2260 has_function_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_function_privilege_name _null_ _null_ _null_ )
+insert ( 2261 has_function_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_function_privilege_id _null_ _null_ _null_ )
+insert ( 2262 has_language_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_language_privilege_name_name _null_ _null_ _null_ )
+insert ( 2263 has_language_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_language_privilege_name_id _null_ _null_ _null_ )
+insert ( 2264 has_language_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_language_privilege_id_name _null_ _null_ _null_ )
+insert ( 2265 has_language_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_language_privilege_id_id _null_ _null_ _null_ )
+insert ( 2266 has_language_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_language_privilege_name _null_ _null_ _null_ )
+insert ( 2267 has_language_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_language_privilege_id _null_ _null_ _null_ )
+insert ( 2268 has_schema_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_schema_privilege_name_name _null_ _null_ _null_ )
+insert ( 2269 has_schema_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_schema_privilege_name_id _null_ _null_ _null_ )
+insert ( 2270 has_schema_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_schema_privilege_id_name _null_ _null_ _null_ )
+insert ( 2271 has_schema_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_schema_privilege_id_id _null_ _null_ _null_ )
+insert ( 2272 has_schema_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_schema_privilege_name _null_ _null_ _null_ )
+insert ( 2273 has_schema_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_schema_privilege_id _null_ _null_ _null_ )
+insert ( 2390 has_tablespace_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_tablespace_privilege_name_name _null_ _null_ _null_ )
+insert ( 2391 has_tablespace_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_tablespace_privilege_name_id _null_ _null_ _null_ )
+insert ( 2392 has_tablespace_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_tablespace_privilege_id_name _null_ _null_ _null_ )
+insert ( 2393 has_tablespace_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_tablespace_privilege_id_id _null_ _null_ _null_ )
+insert ( 2394 has_tablespace_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_tablespace_privilege_name _null_ _null_ _null_ )
+insert ( 2395 has_tablespace_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_tablespace_privilege_id _null_ _null_ _null_ )
+insert ( 3000 has_foreign_data_wrapper_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_name_name _null_ _null_ _null_ )
+insert ( 3001 has_foreign_data_wrapper_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_name_id _null_ _null_ _null_ )
+insert ( 3002 has_foreign_data_wrapper_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_id_name _null_ _null_ _null_ )
+insert ( 3003 has_foreign_data_wrapper_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_id_id _null_ _null_ _null_ )
+insert ( 3004 has_foreign_data_wrapper_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_name _null_ _null_ _null_ )
+insert ( 3005 has_foreign_data_wrapper_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_id _null_ _null_ _null_ )
+insert ( 3006 has_server_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_server_privilege_name_name _null_ _null_ _null_ )
+insert ( 3007 has_server_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_server_privilege_name_id _null_ _null_ _null_ )
+insert ( 3008 has_server_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_server_privilege_id_name _null_ _null_ _null_ )
+insert ( 3009 has_server_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_server_privilege_id_id _null_ _null_ _null_ )
+insert ( 3010 has_server_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_server_privilege_name _null_ _null_ _null_ )
+insert ( 3011 has_server_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_server_privilege_id _null_ _null_ _null_ )
+insert ( 3138 has_type_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ _null_ has_type_privilege_name_name _null_ _null_ _null_ )
+insert ( 3139 has_type_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ has_type_privilege_name_id _null_ _null_ _null_ )
+insert ( 3140 has_type_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ _null_ has_type_privilege_id_name _null_ _null_ _null_ )
+insert ( 3141 has_type_privilege 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ has_type_privilege_id_id _null_ _null_ _null_ )
+insert ( 3142 has_type_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ has_type_privilege_name _null_ _null_ _null_ )
+insert ( 3143 has_type_privilege 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ has_type_privilege_id _null_ _null_ _null_ )
+insert ( 2705 pg_has_role 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 19 25" _null_ _null_ _null_ _null_ _null_ pg_has_role_name_name _null_ _null_ _null_ )
+insert ( 2706 pg_has_role 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ _null_ pg_has_role_name_id _null_ _null_ _null_ )
+insert ( 2707 pg_has_role 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 19 25" _null_ _null_ _null_ _null_ _null_ pg_has_role_id_name _null_ _null_ _null_ )
+insert ( 2708 pg_has_role 11 10 12 1 0 0 0 f f f t f s s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ _null_ pg_has_role_id_id _null_ _null_ _null_ )
+insert ( 2709 pg_has_role 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "19 25" _null_ _null_ _null_ _null_ _null_ pg_has_role_name _null_ _null_ _null_ )
+insert ( 2710 pg_has_role 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ pg_has_role_id _null_ _null_ _null_ )
+insert ( 1269 pg_column_size 11 10 12 1 0 0 0 f f f t f s s 1 0 23 2276 _null_ _null_ _null_ _null_ _null_ pg_column_size _null_ _null_ _null_ )
+insert ( 2322 pg_tablespace_size 11 10 12 1 0 0 0 f f f t f v s 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_tablespace_size_oid _null_ _null_ _null_ )
+insert ( 2323 pg_tablespace_size 11 10 12 1 0 0 0 f f f t f v s 1 0 20 19 _null_ _null_ _null_ _null_ _null_ pg_tablespace_size_name _null_ _null_ _null_ )
+insert ( 2324 pg_database_size 11 10 12 1 0 0 0 f f f t f v s 1 0 20 26 _null_ _null_ _null_ _null_ _null_ pg_database_size_oid _null_ _null_ _null_ )
+insert ( 2168 pg_database_size 11 10 12 1 0 0 0 f f f t f v s 1 0 20 19 _null_ _null_ _null_ _null_ _null_ pg_database_size_name _null_ _null_ _null_ )
+insert ( 2325 pg_relation_size 11 10 14 1 0 0 0 f f f t f v s 1 0 20 2205 _null_ _null_ _null_ _null_ _null_ "select pg_catalog.pg_relation_size($1, ''main'')" _null_ _null_ _null_ )
+insert ( 2332 pg_relation_size 11 10 12 1 0 0 0 f f f t f v s 2 0 20 "2205 25" _null_ _null_ _null_ _null_ _null_ pg_relation_size _null_ _null_ _null_ )
+insert ( 2286 pg_total_relation_size 11 10 12 1 0 0 0 f f f t f v s 1 0 20 2205 _null_ _null_ _null_ _null_ _null_ pg_total_relation_size _null_ _null_ _null_ )
+insert ( 2288 pg_size_pretty 11 10 12 1 0 0 0 f f f t f i s 1 0 25 20 _null_ _null_ _null_ _null_ _null_ pg_size_pretty _null_ _null_ _null_ )
+insert ( 3166 pg_size_pretty 11 10 12 1 0 0 0 f f f t f i s 1 0 25 1700 _null_ _null_ _null_ _null_ _null_ pg_size_pretty_numeric _null_ _null_ _null_ )
+insert ( 3334 pg_size_bytes 11 10 12 1 0 0 0 f f f t f i s 1 0 20 25 _null_ _null_ _null_ _null_ _null_ pg_size_bytes _null_ _null_ _null_ )
+insert ( 2997 pg_table_size 11 10 12 1 0 0 0 f f f t f v s 1 0 20 2205 _null_ _null_ _null_ _null_ _null_ pg_table_size _null_ _null_ _null_ )
+insert ( 2998 pg_indexes_size 11 10 12 1 0 0 0 f f f t f v s 1 0 20 2205 _null_ _null_ _null_ _null_ _null_ pg_indexes_size _null_ _null_ _null_ )
+insert ( 2999 pg_relation_filenode 11 10 12 1 0 0 0 f f f t f s s 1 0 26 2205 _null_ _null_ _null_ _null_ _null_ pg_relation_filenode _null_ _null_ _null_ )
+insert ( 3454 pg_filenode_relation 11 10 12 1 0 0 0 f f f t f s s 2 0 2205 "26 26" _null_ _null_ _null_ _null_ _null_ pg_filenode_relation _null_ _null_ _null_ )
+insert ( 3034 pg_relation_filepath 11 10 12 1 0 0 0 f f f t f s s 1 0 25 2205 _null_ _null_ _null_ _null_ _null_ pg_relation_filepath _null_ _null_ _null_ )
+insert ( 2316 postgresql_fdw_validator 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1009 26" _null_ _null_ _null_ _null_ _null_ postgresql_fdw_validator _null_ _null_ _null_ )
+insert ( 2290 record_in 11 10 12 1 0 0 0 f f f t f s s 3 0 2249 "2275 26 23" _null_ _null_ _null_ _null_ _null_ record_in _null_ _null_ _null_ )
+insert ( 2291 record_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 2249 _null_ _null_ _null_ _null_ _null_ record_out _null_ _null_ _null_ )
+insert ( 2292 cstring_in 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2275 _null_ _null_ _null_ _null_ _null_ cstring_in _null_ _null_ _null_ )
+insert ( 2293 cstring_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2275 _null_ _null_ _null_ _null_ _null_ cstring_out _null_ _null_ _null_ )
+insert ( 2294 any_in 11 10 12 1 0 0 0 f f f t f i s 1 0 2276 2275 _null_ _null_ _null_ _null_ _null_ any_in _null_ _null_ _null_ )
+insert ( 2295 any_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2276 _null_ _null_ _null_ _null_ _null_ any_out _null_ _null_ _null_ )
+insert ( 2296 anyarray_in 11 10 12 1 0 0 0 f f f t f i s 1 0 2277 2275 _null_ _null_ _null_ _null_ _null_ anyarray_in _null_ _null_ _null_ )
+insert ( 2297 anyarray_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 2277 _null_ _null_ _null_ _null_ _null_ anyarray_out _null_ _null_ _null_ )
+insert ( 2298 void_in 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2275 _null_ _null_ _null_ _null_ _null_ void_in _null_ _null_ _null_ )
+insert ( 2299 void_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2278 _null_ _null_ _null_ _null_ _null_ void_out _null_ _null_ _null_ )
+insert ( 2300 trigger_in 11 10 12 1 0 0 0 f f f f f i s 1 0 2279 2275 _null_ _null_ _null_ _null_ _null_ trigger_in _null_ _null_ _null_ )
+insert ( 2301 trigger_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2279 _null_ _null_ _null_ _null_ _null_ trigger_out _null_ _null_ _null_ )
+insert ( 3594 event_trigger_in 11 10 12 1 0 0 0 f f f f f i s 1 0 3838 2275 _null_ _null_ _null_ _null_ _null_ event_trigger_in _null_ _null_ _null_ )
+insert ( 3595 event_trigger_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3838 _null_ _null_ _null_ _null_ _null_ event_trigger_out _null_ _null_ _null_ )
+insert ( 2302 language_handler_in 11 10 12 1 0 0 0 f f f f f i s 1 0 2280 2275 _null_ _null_ _null_ _null_ _null_ language_handler_in _null_ _null_ _null_ )
+insert ( 2303 language_handler_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2280 _null_ _null_ _null_ _null_ _null_ language_handler_out _null_ _null_ _null_ )
+insert ( 2304 internal_in 11 10 12 1 0 0 0 f f f f f i s 1 0 2281 2275 _null_ _null_ _null_ _null_ _null_ internal_in _null_ _null_ _null_ )
+insert ( 2305 internal_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2281 _null_ _null_ _null_ _null_ _null_ internal_out _null_ _null_ _null_ )
+insert ( 2312 anyelement_in 11 10 12 1 0 0 0 f f f t f i s 1 0 2283 2275 _null_ _null_ _null_ _null_ _null_ anyelement_in _null_ _null_ _null_ )
+insert ( 2313 anyelement_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2283 _null_ _null_ _null_ _null_ _null_ anyelement_out _null_ _null_ _null_ )
+insert ( 2398 shell_in 11 10 12 1 0 0 0 f f f f f i s 1 0 2278 2275 _null_ _null_ _null_ _null_ _null_ shell_in _null_ _null_ _null_ )
+insert ( 2399 shell_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2278 _null_ _null_ _null_ _null_ _null_ shell_out _null_ _null_ _null_ )
+insert ( 2597 domain_in 11 10 12 1 0 0 0 f f f f f s s 3 0 2276 "2275 26 23" _null_ _null_ _null_ _null_ _null_ domain_in _null_ _null_ _null_ )
+insert ( 2598 domain_recv 11 10 12 1 0 0 0 f f f f f s s 3 0 2276 "2281 26 23" _null_ _null_ _null_ _null_ _null_ domain_recv _null_ _null_ _null_ )
+insert ( 2777 anynonarray_in 11 10 12 1 0 0 0 f f f t f i s 1 0 2776 2275 _null_ _null_ _null_ _null_ _null_ anynonarray_in _null_ _null_ _null_ )
+insert ( 2778 anynonarray_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2776 _null_ _null_ _null_ _null_ _null_ anynonarray_out _null_ _null_ _null_ )
+insert ( 3116 fdw_handler_in 11 10 12 1 0 0 0 f f f f f i s 1 0 3115 2275 _null_ _null_ _null_ _null_ _null_ fdw_handler_in _null_ _null_ _null_ )
+insert ( 3117 fdw_handler_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3115 _null_ _null_ _null_ _null_ _null_ fdw_handler_out _null_ _null_ _null_ )
+insert ( 326 index_am_handler_in 11 10 12 1 0 0 0 f f f f f i s 1 0 325 2275 _null_ _null_ _null_ _null_ _null_ index_am_handler_in _null_ _null_ _null_ )
+insert ( 327 index_am_handler_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 325 _null_ _null_ _null_ _null_ _null_ index_am_handler_out _null_ _null_ _null_ )
+insert ( 3311 tsm_handler_in 11 10 12 1 0 0 0 f f f f f i s 1 0 3310 2275 _null_ _null_ _null_ _null_ _null_ tsm_handler_in _null_ _null_ _null_ )
+insert ( 3312 tsm_handler_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3310 _null_ _null_ _null_ _null_ _null_ tsm_handler_out _null_ _null_ _null_ )
+insert ( 267 table_am_handler_in 11 10 12 1 0 0 0 f f f f f i s 1 0 269 2275 _null_ _null_ _null_ _null_ _null_ table_am_handler_in _null_ _null_ _null_ )
+insert ( 268 table_am_handler_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 269 _null_ _null_ _null_ _null_ _null_ table_am_handler_out _null_ _null_ _null_ )
+insert ( 5086 anycompatible_in 11 10 12 1 0 0 0 f f f t f i s 1 0 5077 2275 _null_ _null_ _null_ _null_ _null_ anycompatible_in _null_ _null_ _null_ )
+insert ( 5087 anycompatible_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 5077 _null_ _null_ _null_ _null_ _null_ anycompatible_out _null_ _null_ _null_ )
+insert ( 5088 anycompatiblearray_in 11 10 12 1 0 0 0 f f f t f i s 1 0 5078 2275 _null_ _null_ _null_ _null_ _null_ anycompatiblearray_in _null_ _null_ _null_ )
+insert ( 5089 anycompatiblearray_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 5078 _null_ _null_ _null_ _null_ _null_ anycompatiblearray_out _null_ _null_ _null_ )
+insert ( 5090 anycompatiblearray_recv 11 10 12 1 0 0 0 f f f t f s s 1 0 5078 2281 _null_ _null_ _null_ _null_ _null_ anycompatiblearray_recv _null_ _null_ _null_ )
+insert ( 5091 anycompatiblearray_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 5078 _null_ _null_ _null_ _null_ _null_ anycompatiblearray_send _null_ _null_ _null_ )
+insert ( 5092 anycompatiblenonarray_in 11 10 12 1 0 0 0 f f f t f i s 1 0 5079 2275 _null_ _null_ _null_ _null_ _null_ anycompatiblenonarray_in _null_ _null_ _null_ )
+insert ( 5093 anycompatiblenonarray_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 5079 _null_ _null_ _null_ _null_ _null_ anycompatiblenonarray_out _null_ _null_ _null_ )
+insert ( 5094 anycompatiblerange_in 11 10 12 1 0 0 0 f f f t f s s 3 0 5080 "2275 26 23" _null_ _null_ _null_ _null_ _null_ anycompatiblerange_in _null_ _null_ _null_ )
+insert ( 5095 anycompatiblerange_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 5080 _null_ _null_ _null_ _null_ _null_ anycompatiblerange_out _null_ _null_ _null_ )
+insert ( 3313 bernoulli 11 10 12 1 0 0 0 f f f t f v s 1 0 3310 2281 _null_ _null_ _null_ _null_ _null_ tsm_bernoulli_handler _null_ _null_ _null_ )
+insert ( 3314 system 11 10 12 1 0 0 0 f f f t f v s 1 0 3310 2281 _null_ _null_ _null_ _null_ _null_ tsm_system_handler _null_ _null_ _null_ )
+insert ( 2311 md5 11 10 12 1 0 0 0 f f t t f i s 1 0 25 25 _null_ _null_ _null_ _null_ _null_ md5_text _null_ _null_ _null_ )
+insert ( 2321 md5 11 10 12 1 0 0 0 f f t t f i s 1 0 25 17 _null_ _null_ _null_ _null_ _null_ md5_bytea _null_ _null_ _null_ )
+insert ( 3419 sha224 11 10 12 1 0 0 0 f f t t f i s 1 0 17 17 _null_ _null_ _null_ _null_ _null_ sha224_bytea _null_ _null_ _null_ )
+insert ( 3420 sha256 11 10 12 1 0 0 0 f f t t f i s 1 0 17 17 _null_ _null_ _null_ _null_ _null_ sha256_bytea _null_ _null_ _null_ )
+insert ( 3421 sha384 11 10 12 1 0 0 0 f f t t f i s 1 0 17 17 _null_ _null_ _null_ _null_ _null_ sha384_bytea _null_ _null_ _null_ )
+insert ( 3422 sha512 11 10 12 1 0 0 0 f f t t f i s 1 0 17 17 _null_ _null_ _null_ _null_ _null_ sha512_bytea _null_ _null_ _null_ )
+insert ( 2338 date_lt_timestamp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1082 1114" _null_ _null_ _null_ _null_ _null_ date_lt_timestamp _null_ _null_ _null_ )
+insert ( 2339 date_le_timestamp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1082 1114" _null_ _null_ _null_ _null_ _null_ date_le_timestamp _null_ _null_ _null_ )
+insert ( 2340 date_eq_timestamp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1082 1114" _null_ _null_ _null_ _null_ _null_ date_eq_timestamp _null_ _null_ _null_ )
+insert ( 2341 date_gt_timestamp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1082 1114" _null_ _null_ _null_ _null_ _null_ date_gt_timestamp _null_ _null_ _null_ )
+insert ( 2342 date_ge_timestamp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1082 1114" _null_ _null_ _null_ _null_ _null_ date_ge_timestamp _null_ _null_ _null_ )
+insert ( 2343 date_ne_timestamp 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1082 1114" _null_ _null_ _null_ _null_ _null_ date_ne_timestamp _null_ _null_ _null_ )
+insert ( 2344 date_cmp_timestamp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "1082 1114" _null_ _null_ _null_ _null_ _null_ date_cmp_timestamp _null_ _null_ _null_ )
+insert ( 2351 date_lt_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1082 1184" _null_ _null_ _null_ _null_ _null_ date_lt_timestamptz _null_ _null_ _null_ )
+insert ( 2352 date_le_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1082 1184" _null_ _null_ _null_ _null_ _null_ date_le_timestamptz _null_ _null_ _null_ )
+insert ( 2353 date_eq_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1082 1184" _null_ _null_ _null_ _null_ _null_ date_eq_timestamptz _null_ _null_ _null_ )
+insert ( 2354 date_gt_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1082 1184" _null_ _null_ _null_ _null_ _null_ date_gt_timestamptz _null_ _null_ _null_ )
+insert ( 2355 date_ge_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1082 1184" _null_ _null_ _null_ _null_ _null_ date_ge_timestamptz _null_ _null_ _null_ )
+insert ( 2356 date_ne_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1082 1184" _null_ _null_ _null_ _null_ _null_ date_ne_timestamptz _null_ _null_ _null_ )
+insert ( 2357 date_cmp_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 23 "1082 1184" _null_ _null_ _null_ _null_ _null_ date_cmp_timestamptz _null_ _null_ _null_ )
+insert ( 2364 timestamp_lt_date 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1114 1082" _null_ _null_ _null_ _null_ _null_ timestamp_lt_date _null_ _null_ _null_ )
+insert ( 2365 timestamp_le_date 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1114 1082" _null_ _null_ _null_ _null_ _null_ timestamp_le_date _null_ _null_ _null_ )
+insert ( 2366 timestamp_eq_date 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1114 1082" _null_ _null_ _null_ _null_ _null_ timestamp_eq_date _null_ _null_ _null_ )
+insert ( 2367 timestamp_gt_date 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1114 1082" _null_ _null_ _null_ _null_ _null_ timestamp_gt_date _null_ _null_ _null_ )
+insert ( 2368 timestamp_ge_date 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1114 1082" _null_ _null_ _null_ _null_ _null_ timestamp_ge_date _null_ _null_ _null_ )
+insert ( 2369 timestamp_ne_date 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "1114 1082" _null_ _null_ _null_ _null_ _null_ timestamp_ne_date _null_ _null_ _null_ )
+insert ( 2370 timestamp_cmp_date 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "1114 1082" _null_ _null_ _null_ _null_ _null_ timestamp_cmp_date _null_ _null_ _null_ )
+insert ( 2377 timestamptz_lt_date 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1082" _null_ _null_ _null_ _null_ _null_ timestamptz_lt_date _null_ _null_ _null_ )
+insert ( 2378 timestamptz_le_date 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1082" _null_ _null_ _null_ _null_ _null_ timestamptz_le_date _null_ _null_ _null_ )
+insert ( 2379 timestamptz_eq_date 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1082" _null_ _null_ _null_ _null_ _null_ timestamptz_eq_date _null_ _null_ _null_ )
+insert ( 2380 timestamptz_gt_date 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1082" _null_ _null_ _null_ _null_ _null_ timestamptz_gt_date _null_ _null_ _null_ )
+insert ( 2381 timestamptz_ge_date 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1082" _null_ _null_ _null_ _null_ _null_ timestamptz_ge_date _null_ _null_ _null_ )
+insert ( 2382 timestamptz_ne_date 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1082" _null_ _null_ _null_ _null_ _null_ timestamptz_ne_date _null_ _null_ _null_ )
+insert ( 2383 timestamptz_cmp_date 11 10 12 1 0 0 0 f f f t f s s 2 0 23 "1184 1082" _null_ _null_ _null_ _null_ _null_ timestamptz_cmp_date _null_ _null_ _null_ )
+insert ( 2520 timestamp_lt_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1114 1184" _null_ _null_ _null_ _null_ _null_ timestamp_lt_timestamptz _null_ _null_ _null_ )
+insert ( 2521 timestamp_le_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1114 1184" _null_ _null_ _null_ _null_ _null_ timestamp_le_timestamptz _null_ _null_ _null_ )
+insert ( 2522 timestamp_eq_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1114 1184" _null_ _null_ _null_ _null_ _null_ timestamp_eq_timestamptz _null_ _null_ _null_ )
+insert ( 2523 timestamp_gt_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1114 1184" _null_ _null_ _null_ _null_ _null_ timestamp_gt_timestamptz _null_ _null_ _null_ )
+insert ( 2524 timestamp_ge_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1114 1184" _null_ _null_ _null_ _null_ _null_ timestamp_ge_timestamptz _null_ _null_ _null_ )
+insert ( 2525 timestamp_ne_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1114 1184" _null_ _null_ _null_ _null_ _null_ timestamp_ne_timestamptz _null_ _null_ _null_ )
+insert ( 2526 timestamp_cmp_timestamptz 11 10 12 1 0 0 0 f f f t f s s 2 0 23 "1114 1184" _null_ _null_ _null_ _null_ _null_ timestamp_cmp_timestamptz _null_ _null_ _null_ )
+insert ( 2527 timestamptz_lt_timestamp 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1114" _null_ _null_ _null_ _null_ _null_ timestamptz_lt_timestamp _null_ _null_ _null_ )
+insert ( 2528 timestamptz_le_timestamp 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1114" _null_ _null_ _null_ _null_ _null_ timestamptz_le_timestamp _null_ _null_ _null_ )
+insert ( 2529 timestamptz_eq_timestamp 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1114" _null_ _null_ _null_ _null_ _null_ timestamptz_eq_timestamp _null_ _null_ _null_ )
+insert ( 2530 timestamptz_gt_timestamp 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1114" _null_ _null_ _null_ _null_ _null_ timestamptz_gt_timestamp _null_ _null_ _null_ )
+insert ( 2531 timestamptz_ge_timestamp 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1114" _null_ _null_ _null_ _null_ _null_ timestamptz_ge_timestamp _null_ _null_ _null_ )
+insert ( 2532 timestamptz_ne_timestamp 11 10 12 1 0 0 0 f f f t f s s 2 0 16 "1184 1114" _null_ _null_ _null_ _null_ _null_ timestamptz_ne_timestamp _null_ _null_ _null_ )
+insert ( 2533 timestamptz_cmp_timestamp 11 10 12 1 0 0 0 f f f t f s s 2 0 23 "1184 1114" _null_ _null_ _null_ _null_ _null_ timestamptz_cmp_timestamp _null_ _null_ _null_ )
+insert ( 2400 array_recv 11 10 12 1 0 0 0 f f f t f s s 3 0 2277 "2281 26 23" _null_ _null_ _null_ _null_ _null_ array_recv _null_ _null_ _null_ )
+insert ( 2401 array_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 2277 _null_ _null_ _null_ _null_ _null_ array_send _null_ _null_ _null_ )
+insert ( 2402 record_recv 11 10 12 1 0 0 0 f f f t f s s 3 0 2249 "2281 26 23" _null_ _null_ _null_ _null_ _null_ record_recv _null_ _null_ _null_ )
+insert ( 2403 record_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 2249 _null_ _null_ _null_ _null_ _null_ record_send _null_ _null_ _null_ )
+insert ( 2404 int2recv 11 10 12 1 0 0 0 f f f t f i s 1 0 21 2281 _null_ _null_ _null_ _null_ _null_ int2recv _null_ _null_ _null_ )
+insert ( 2405 int2send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 21 _null_ _null_ _null_ _null_ _null_ int2send _null_ _null_ _null_ )
+insert ( 2406 int4recv 11 10 12 1 0 0 0 f f f t f i s 1 0 23 2281 _null_ _null_ _null_ _null_ _null_ int4recv _null_ _null_ _null_ )
+insert ( 2407 int4send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 23 _null_ _null_ _null_ _null_ _null_ int4send _null_ _null_ _null_ )
+insert ( 2408 int8recv 11 10 12 1 0 0 0 f f f t f i s 1 0 20 2281 _null_ _null_ _null_ _null_ _null_ int8recv _null_ _null_ _null_ )
+insert ( 2409 int8send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 20 _null_ _null_ _null_ _null_ _null_ int8send _null_ _null_ _null_ )
+insert ( 2410 int2vectorrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 22 2281 _null_ _null_ _null_ _null_ _null_ int2vectorrecv _null_ _null_ _null_ )
+insert ( 2411 int2vectorsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 22 _null_ _null_ _null_ _null_ _null_ int2vectorsend _null_ _null_ _null_ )
+insert ( 2412 bytearecv 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2281 _null_ _null_ _null_ _null_ _null_ bytearecv _null_ _null_ _null_ )
+insert ( 2413 byteasend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 17 _null_ _null_ _null_ _null_ _null_ byteasend _null_ _null_ _null_ )
+insert ( 2414 textrecv 11 10 12 1 0 0 0 f f f t f s s 1 0 25 2281 _null_ _null_ _null_ _null_ _null_ textrecv _null_ _null_ _null_ )
+insert ( 2415 textsend 11 10 12 1 0 0 0 f f f t f s s 1 0 17 25 _null_ _null_ _null_ _null_ _null_ textsend _null_ _null_ _null_ )
+insert ( 2416 unknownrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 705 2281 _null_ _null_ _null_ _null_ _null_ unknownrecv _null_ _null_ _null_ )
+insert ( 2417 unknownsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 705 _null_ _null_ _null_ _null_ _null_ unknownsend _null_ _null_ _null_ )
+insert ( 2418 oidrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 26 2281 _null_ _null_ _null_ _null_ _null_ oidrecv _null_ _null_ _null_ )
+insert ( 2419 oidsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 26 _null_ _null_ _null_ _null_ _null_ oidsend _null_ _null_ _null_ )
+insert ( 2420 oidvectorrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 30 2281 _null_ _null_ _null_ _null_ _null_ oidvectorrecv _null_ _null_ _null_ )
+insert ( 2421 oidvectorsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 30 _null_ _null_ _null_ _null_ _null_ oidvectorsend _null_ _null_ _null_ )
+insert ( 2422 namerecv 11 10 12 1 0 0 0 f f f t f s s 1 0 19 2281 _null_ _null_ _null_ _null_ _null_ namerecv _null_ _null_ _null_ )
+insert ( 2423 namesend 11 10 12 1 0 0 0 f f f t f s s 1 0 17 19 _null_ _null_ _null_ _null_ _null_ namesend _null_ _null_ _null_ )
+insert ( 2424 float4recv 11 10 12 1 0 0 0 f f f t f i s 1 0 700 2281 _null_ _null_ _null_ _null_ _null_ float4recv _null_ _null_ _null_ )
+insert ( 2425 float4send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 700 _null_ _null_ _null_ _null_ _null_ float4send _null_ _null_ _null_ )
+insert ( 2426 float8recv 11 10 12 1 0 0 0 f f f t f i s 1 0 701 2281 _null_ _null_ _null_ _null_ _null_ float8recv _null_ _null_ _null_ )
+insert ( 2427 float8send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 701 _null_ _null_ _null_ _null_ _null_ float8send _null_ _null_ _null_ )
+insert ( 2428 point_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 600 2281 _null_ _null_ _null_ _null_ _null_ point_recv _null_ _null_ _null_ )
+insert ( 2429 point_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 600 _null_ _null_ _null_ _null_ _null_ point_send _null_ _null_ _null_ )
+insert ( 2430 bpcharrecv 11 10 12 1 0 0 0 f f f t f s s 3 0 1042 "2281 26 23" _null_ _null_ _null_ _null_ _null_ bpcharrecv _null_ _null_ _null_ )
+insert ( 2431 bpcharsend 11 10 12 1 0 0 0 f f f t f s s 1 0 17 1042 _null_ _null_ _null_ _null_ _null_ bpcharsend _null_ _null_ _null_ )
+insert ( 2432 varcharrecv 11 10 12 1 0 0 0 f f f t f s s 3 0 1043 "2281 26 23" _null_ _null_ _null_ _null_ _null_ varcharrecv _null_ _null_ _null_ )
+insert ( 2433 varcharsend 11 10 12 1 0 0 0 f f f t f s s 1 0 17 1043 _null_ _null_ _null_ _null_ _null_ varcharsend _null_ _null_ _null_ )
+insert ( 2434 charrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 18 2281 _null_ _null_ _null_ _null_ _null_ charrecv _null_ _null_ _null_ )
+insert ( 2435 charsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 18 _null_ _null_ _null_ _null_ _null_ charsend _null_ _null_ _null_ )
+insert ( 2436 boolrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 16 2281 _null_ _null_ _null_ _null_ _null_ boolrecv _null_ _null_ _null_ )
+insert ( 2437 boolsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 16 _null_ _null_ _null_ _null_ _null_ boolsend _null_ _null_ _null_ )
+insert ( 2438 tidrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 27 2281 _null_ _null_ _null_ _null_ _null_ tidrecv _null_ _null_ _null_ )
+insert ( 2439 tidsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 27 _null_ _null_ _null_ _null_ _null_ tidsend _null_ _null_ _null_ )
+insert ( 2440 xidrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 28 2281 _null_ _null_ _null_ _null_ _null_ xidrecv _null_ _null_ _null_ )
+insert ( 2441 xidsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 28 _null_ _null_ _null_ _null_ _null_ xidsend _null_ _null_ _null_ )
+insert ( 2442 cidrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 29 2281 _null_ _null_ _null_ _null_ _null_ cidrecv _null_ _null_ _null_ )
+insert ( 2443 cidsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 29 _null_ _null_ _null_ _null_ _null_ cidsend _null_ _null_ _null_ )
+insert ( 2444 regprocrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 24 2281 _null_ _null_ _null_ _null_ _null_ regprocrecv _null_ _null_ _null_ )
+insert ( 2445 regprocsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 24 _null_ _null_ _null_ _null_ _null_ regprocsend _null_ _null_ _null_ )
+insert ( 2446 regprocedurerecv 11 10 12 1 0 0 0 f f f t f i s 1 0 2202 2281 _null_ _null_ _null_ _null_ _null_ regprocedurerecv _null_ _null_ _null_ )
+insert ( 2447 regproceduresend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2202 _null_ _null_ _null_ _null_ _null_ regproceduresend _null_ _null_ _null_ )
+insert ( 2448 regoperrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 2203 2281 _null_ _null_ _null_ _null_ _null_ regoperrecv _null_ _null_ _null_ )
+insert ( 2449 regopersend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2203 _null_ _null_ _null_ _null_ _null_ regopersend _null_ _null_ _null_ )
+insert ( 2450 regoperatorrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 2204 2281 _null_ _null_ _null_ _null_ _null_ regoperatorrecv _null_ _null_ _null_ )
+insert ( 2451 regoperatorsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2204 _null_ _null_ _null_ _null_ _null_ regoperatorsend _null_ _null_ _null_ )
+insert ( 2452 regclassrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 2205 2281 _null_ _null_ _null_ _null_ _null_ regclassrecv _null_ _null_ _null_ )
+insert ( 2453 regclasssend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2205 _null_ _null_ _null_ _null_ _null_ regclasssend _null_ _null_ _null_ )
+insert ( 4196 regcollationrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 4191 2281 _null_ _null_ _null_ _null_ _null_ regcollationrecv _null_ _null_ _null_ )
+insert ( 4197 regcollationsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 4191 _null_ _null_ _null_ _null_ _null_ regcollationsend _null_ _null_ _null_ )
+insert ( 2454 regtyperecv 11 10 12 1 0 0 0 f f f t f i s 1 0 2206 2281 _null_ _null_ _null_ _null_ _null_ regtyperecv _null_ _null_ _null_ )
+insert ( 2455 regtypesend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2206 _null_ _null_ _null_ _null_ _null_ regtypesend _null_ _null_ _null_ )
+insert ( 4094 regrolerecv 11 10 12 1 0 0 0 f f f t f i s 1 0 4096 2281 _null_ _null_ _null_ _null_ _null_ regrolerecv _null_ _null_ _null_ )
+insert ( 4095 regrolesend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 4096 _null_ _null_ _null_ _null_ _null_ regrolesend _null_ _null_ _null_ )
+insert ( 4087 regnamespacerecv 11 10 12 1 0 0 0 f f f t f i s 1 0 4089 2281 _null_ _null_ _null_ _null_ _null_ regnamespacerecv _null_ _null_ _null_ )
+insert ( 4088 regnamespacesend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 4089 _null_ _null_ _null_ _null_ _null_ regnamespacesend _null_ _null_ _null_ )
+insert ( 2456 bit_recv 11 10 12 1 0 0 0 f f f t f i s 3 0 1560 "2281 26 23" _null_ _null_ _null_ _null_ _null_ bit_recv _null_ _null_ _null_ )
+insert ( 2457 bit_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 1560 _null_ _null_ _null_ _null_ _null_ bit_send _null_ _null_ _null_ )
+insert ( 2458 varbit_recv 11 10 12 1 0 0 0 f f f t f i s 3 0 1562 "2281 26 23" _null_ _null_ _null_ _null_ _null_ varbit_recv _null_ _null_ _null_ )
+insert ( 2459 varbit_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 1562 _null_ _null_ _null_ _null_ _null_ varbit_send _null_ _null_ _null_ )
+insert ( 2460 numeric_recv 11 10 12 1 0 0 0 f f f t f i s 3 0 1700 "2281 26 23" _null_ _null_ _null_ _null_ _null_ numeric_recv _null_ _null_ _null_ )
+insert ( 2461 numeric_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 1700 _null_ _null_ _null_ _null_ _null_ numeric_send _null_ _null_ _null_ )
+insert ( 2468 date_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 1082 2281 _null_ _null_ _null_ _null_ _null_ date_recv _null_ _null_ _null_ )
+insert ( 2469 date_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 1082 _null_ _null_ _null_ _null_ _null_ date_send _null_ _null_ _null_ )
+insert ( 2470 time_recv 11 10 12 1 0 0 0 f f f t f i s 3 0 1083 "2281 26 23" _null_ _null_ _null_ _null_ _null_ time_recv _null_ _null_ _null_ )
+insert ( 2471 time_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 1083 _null_ _null_ _null_ _null_ _null_ time_send _null_ _null_ _null_ )
+insert ( 2472 timetz_recv 11 10 12 1 0 0 0 f f f t f i s 3 0 1266 "2281 26 23" _null_ _null_ _null_ _null_ _null_ timetz_recv _null_ _null_ _null_ )
+insert ( 2473 timetz_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 1266 _null_ _null_ _null_ _null_ _null_ timetz_send _null_ _null_ _null_ )
+insert ( 2474 timestamp_recv 11 10 12 1 0 0 0 f f f t f i s 3 0 1114 "2281 26 23" _null_ _null_ _null_ _null_ _null_ timestamp_recv _null_ _null_ _null_ )
+insert ( 2475 timestamp_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 1114 _null_ _null_ _null_ _null_ _null_ timestamp_send _null_ _null_ _null_ )
+insert ( 2476 timestamptz_recv 11 10 12 1 0 0 0 f f f t f i s 3 0 1184 "2281 26 23" _null_ _null_ _null_ _null_ _null_ timestamptz_recv _null_ _null_ _null_ )
+insert ( 2477 timestamptz_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 1184 _null_ _null_ _null_ _null_ _null_ timestamptz_send _null_ _null_ _null_ )
+insert ( 2478 interval_recv 11 10 12 1 0 0 0 f f f t f i s 3 0 1186 "2281 26 23" _null_ _null_ _null_ _null_ _null_ interval_recv _null_ _null_ _null_ )
+insert ( 2479 interval_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 1186 _null_ _null_ _null_ _null_ _null_ interval_send _null_ _null_ _null_ )
+insert ( 2480 lseg_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 601 2281 _null_ _null_ _null_ _null_ _null_ lseg_recv _null_ _null_ _null_ )
+insert ( 2481 lseg_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 601 _null_ _null_ _null_ _null_ _null_ lseg_send _null_ _null_ _null_ )
+insert ( 2482 path_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 602 2281 _null_ _null_ _null_ _null_ _null_ path_recv _null_ _null_ _null_ )
+insert ( 2483 path_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 602 _null_ _null_ _null_ _null_ _null_ path_send _null_ _null_ _null_ )
+insert ( 2484 box_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 603 2281 _null_ _null_ _null_ _null_ _null_ box_recv _null_ _null_ _null_ )
+insert ( 2485 box_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 603 _null_ _null_ _null_ _null_ _null_ box_send _null_ _null_ _null_ )
+insert ( 2486 poly_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 604 2281 _null_ _null_ _null_ _null_ _null_ poly_recv _null_ _null_ _null_ )
+insert ( 2487 poly_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 604 _null_ _null_ _null_ _null_ _null_ poly_send _null_ _null_ _null_ )
+insert ( 2488 line_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 628 2281 _null_ _null_ _null_ _null_ _null_ line_recv _null_ _null_ _null_ )
+insert ( 2489 line_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 628 _null_ _null_ _null_ _null_ _null_ line_send _null_ _null_ _null_ )
+insert ( 2490 circle_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 718 2281 _null_ _null_ _null_ _null_ _null_ circle_recv _null_ _null_ _null_ )
+insert ( 2491 circle_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 718 _null_ _null_ _null_ _null_ _null_ circle_send _null_ _null_ _null_ )
+insert ( 2492 cash_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 790 2281 _null_ _null_ _null_ _null_ _null_ cash_recv _null_ _null_ _null_ )
+insert ( 2493 cash_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 790 _null_ _null_ _null_ _null_ _null_ cash_send _null_ _null_ _null_ )
+insert ( 2494 macaddr_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 829 2281 _null_ _null_ _null_ _null_ _null_ macaddr_recv _null_ _null_ _null_ )
+insert ( 2495 macaddr_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 829 _null_ _null_ _null_ _null_ _null_ macaddr_send _null_ _null_ _null_ )
+insert ( 2496 inet_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 869 2281 _null_ _null_ _null_ _null_ _null_ inet_recv _null_ _null_ _null_ )
+insert ( 2497 inet_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 869 _null_ _null_ _null_ _null_ _null_ inet_send _null_ _null_ _null_ )
+insert ( 2498 cidr_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 650 2281 _null_ _null_ _null_ _null_ _null_ cidr_recv _null_ _null_ _null_ )
+insert ( 2499 cidr_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 650 _null_ _null_ _null_ _null_ _null_ cidr_send _null_ _null_ _null_ )
+insert ( 2500 cstring_recv 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 2281 _null_ _null_ _null_ _null_ _null_ cstring_recv _null_ _null_ _null_ )
+insert ( 2501 cstring_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 2275 _null_ _null_ _null_ _null_ _null_ cstring_send _null_ _null_ _null_ )
+insert ( 2502 anyarray_recv 11 10 12 1 0 0 0 f f f t f s s 1 0 2277 2281 _null_ _null_ _null_ _null_ _null_ anyarray_recv _null_ _null_ _null_ )
+insert ( 2503 anyarray_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 2277 _null_ _null_ _null_ _null_ _null_ anyarray_send _null_ _null_ _null_ )
+insert ( 3120 void_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ void_recv _null_ _null_ _null_ )
+insert ( 3121 void_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2278 _null_ _null_ _null_ _null_ _null_ void_send _null_ _null_ _null_ )
+insert ( 3446 macaddr8_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 774 2281 _null_ _null_ _null_ _null_ _null_ macaddr8_recv _null_ _null_ _null_ )
+insert ( 3447 macaddr8_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 774 _null_ _null_ _null_ _null_ _null_ macaddr8_send _null_ _null_ _null_ )
+insert ( 2504 pg_get_ruledef 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "26 16" _null_ _null_ _null_ _null_ _null_ pg_get_ruledef_ext _null_ _null_ _null_ )
+insert ( 2505 pg_get_viewdef 11 10 12 1 0 0 0 f f f t f s r 2 0 25 "25 16" _null_ _null_ _null_ _null_ _null_ pg_get_viewdef_name_ext _null_ _null_ _null_ )
+insert ( 2506 pg_get_viewdef 11 10 12 1 0 0 0 f f f t f s r 2 0 25 "26 16" _null_ _null_ _null_ _null_ _null_ pg_get_viewdef_ext _null_ _null_ _null_ )
+insert ( 3159 pg_get_viewdef 11 10 12 1 0 0 0 f f f t f s r 2 0 25 "26 23" _null_ _null_ _null_ _null_ _null_ pg_get_viewdef_wrap _null_ _null_ _null_ )
+insert ( 2507 pg_get_indexdef 11 10 12 1 0 0 0 f f f t f s s 3 0 25 "26 23 16" _null_ _null_ _null_ _null_ _null_ pg_get_indexdef_ext _null_ _null_ _null_ )
+insert ( 2508 pg_get_constraintdef 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "26 16" _null_ _null_ _null_ _null_ _null_ pg_get_constraintdef_ext _null_ _null_ _null_ )
+insert ( 2509 pg_get_expr 11 10 12 1 0 0 0 f f f t f s s 3 0 25 "194 26 16" _null_ _null_ _null_ _null_ _null_ pg_get_expr_ext _null_ _null_ _null_ )
+insert ( 2510 pg_prepared_statement 11 10 12 1 1000 0 0 f f f t t s r 0 0 2249 "" "{25,25,1184,2211,16}" "{o,o,o,o,o}" "{name,statement,prepare_time,parameter_types,from_sql}" _null_ _null_ pg_prepared_statement _null_ _null_ _null_ )
+insert ( 2511 pg_cursor 11 10 12 1 1000 0 0 f f f t t s r 0 0 2249 "" "{25,25,16,16,16,1184}" "{o,o,o,o,o,o}" "{name,statement,is_holdable,is_binary,is_scrollable,creation_time}" _null_ _null_ pg_cursor _null_ _null_ _null_ )
+insert ( 2599 pg_timezone_abbrevs 11 10 12 1 1000 0 0 f f f t t s s 0 0 2249 "" "{25,1186,16}" "{o,o,o}" "{abbrev,utc_offset,is_dst}" _null_ _null_ pg_timezone_abbrevs _null_ _null_ _null_ )
+insert ( 2856 pg_timezone_names 11 10 12 1 1000 0 0 f f f t t s s 0 0 2249 "" "{25,25,1186,16}" "{o,o,o,o}" "{name,abbrev,utc_offset,is_dst}" _null_ _null_ pg_timezone_names _null_ _null_ _null_ )
+insert ( 2730 pg_get_triggerdef 11 10 12 1 0 0 0 f f f t f s s 2 0 25 "26 16" _null_ _null_ _null_ _null_ _null_ pg_get_triggerdef_ext _null_ _null_ _null_ )
+insert ( 3035 pg_listening_channels 11 10 12 1 10 0 0 f f f t t s r 0 0 25 "" _null_ _null_ _null_ _null_ _null_ pg_listening_channels _null_ _null_ _null_ )
+insert ( 3036 pg_notify 11 10 12 1 0 0 0 f f f f f v r 2 0 2278 "25 25" _null_ _null_ _null_ _null_ _null_ pg_notify _null_ _null_ _null_ )
+insert ( 3296 pg_notification_queue_usage 11 10 12 1 0 0 0 f f f t f v r 0 0 701 "" _null_ _null_ _null_ _null_ _null_ pg_notification_queue_usage _null_ _null_ _null_ )
+insert ( 5052 pg_get_shmem_allocations 11 10 12 1 50 0 0 f f f t t v s 0 0 2249 "" "{25,20,20,20}" "{o,o,o,o}" "{name,off,size,allocated_size}" _null_ _null_ pg_get_shmem_allocations _null_ _null_ _null_ )
+insert ( 1066 generate_series 11 10 12 1 1000 0 3994 f f f t t i s 3 0 23 "23 23 23" _null_ _null_ _null_ _null_ _null_ generate_series_step_int4 _null_ _null_ _null_ )
+insert ( 1067 generate_series 11 10 12 1 1000 0 3994 f f f t t i s 2 0 23 "23 23" _null_ _null_ _null_ _null_ _null_ generate_series_int4 _null_ _null_ _null_ )
+insert ( 3994 generate_series_int4_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ generate_series_int4_support _null_ _null_ _null_ )
+insert ( 1068 generate_series 11 10 12 1 1000 0 3995 f f f t t i s 3 0 20 "20 20 20" _null_ _null_ _null_ _null_ _null_ generate_series_step_int8 _null_ _null_ _null_ )
+insert ( 1069 generate_series 11 10 12 1 1000 0 3995 f f f t t i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ generate_series_int8 _null_ _null_ _null_ )
+insert ( 3995 generate_series_int8_support 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ generate_series_int8_support _null_ _null_ _null_ )
+insert ( 3259 generate_series 11 10 12 1 1000 0 0 f f f t t i s 3 0 1700 "1700 1700 1700" _null_ _null_ _null_ _null_ _null_ generate_series_step_numeric _null_ _null_ _null_ )
+insert ( 3260 generate_series 11 10 12 1 1000 0 0 f f f t t i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_ generate_series_numeric _null_ _null_ _null_ )
+insert ( 938 generate_series 11 10 12 1 1000 0 0 f f f t t i s 3 0 1114 "1114 1114 1186" _null_ _null_ _null_ _null_ _null_ generate_series_timestamp _null_ _null_ _null_ )
+insert ( 939 generate_series 11 10 12 1 1000 0 0 f f f t t s s 3 0 1184 "1184 1184 1186" _null_ _null_ _null_ _null_ _null_ generate_series_timestamptz _null_ _null_ _null_ )
+insert ( 2515 booland_statefunc 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "16 16" _null_ _null_ _null_ _null_ _null_ booland_statefunc _null_ _null_ _null_ )
+insert ( 2516 boolor_statefunc 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "16 16" _null_ _null_ _null_ _null_ _null_ boolor_statefunc _null_ _null_ _null_ )
+insert ( 3496 bool_accum 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 16" _null_ _null_ _null_ _null_ _null_ bool_accum _null_ _null_ _null_ )
+insert ( 3497 bool_accum_inv 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 16" _null_ _null_ _null_ _null_ _null_ bool_accum_inv _null_ _null_ _null_ )
+insert ( 3498 bool_alltrue 11 10 12 1 0 0 0 f f f t f i s 1 0 16 2281 _null_ _null_ _null_ _null_ _null_ bool_alltrue _null_ _null_ _null_ )
+insert ( 3499 bool_anytrue 11 10 12 1 0 0 0 f f f t f i s 1 0 16 2281 _null_ _null_ _null_ _null_ _null_ bool_anytrue _null_ _null_ _null_ )
+insert ( 2517 bool_and 11 10 12 1 0 0 0 a f f f f i s 1 0 16 16 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2518 bool_or 11 10 12 1 0 0 0 a f f f f i s 1 0 16 16 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2519 every 11 10 12 1 0 0 0 a f f f f i s 1 0 16 16 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2236 bit_and 11 10 12 1 0 0 0 a f f f f i s 1 0 21 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2237 bit_or 11 10 12 1 0 0 0 a f f f f i s 1 0 21 21 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2238 bit_and 11 10 12 1 0 0 0 a f f f f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2239 bit_or 11 10 12 1 0 0 0 a f f f f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2240 bit_and 11 10 12 1 0 0 0 a f f f f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2241 bit_or 11 10 12 1 0 0 0 a f f f f i s 1 0 20 20 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2242 bit_and 11 10 12 1 0 0 0 a f f f f i s 1 0 1560 1560 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2243 bit_or 11 10 12 1 0 0 0 a f f f f i s 1 0 1560 1560 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2546 interval_pl_date 11 10 14 1 0 0 0 f f f t f i s 2 0 1114 "1186 1082" _null_ _null_ _null_ _null_ _null_ "select $2 + $1" _null_ _null_ _null_ )
+insert ( 2547 interval_pl_timetz 11 10 14 1 0 0 0 f f f t f i s 2 0 1266 "1186 1266" _null_ _null_ _null_ _null_ _null_ "select $2 + $1" _null_ _null_ _null_ )
+insert ( 2548 interval_pl_timestamp 11 10 14 1 0 0 0 f f f t f i s 2 0 1114 "1186 1114" _null_ _null_ _null_ _null_ _null_ "select $2 + $1" _null_ _null_ _null_ )
+insert ( 2549 interval_pl_timestamptz 11 10 14 1 0 0 0 f f f t f s s 2 0 1184 "1186 1184" _null_ _null_ _null_ _null_ _null_ "select $2 + $1" _null_ _null_ _null_ )
+insert ( 2550 integer_pl_date 11 10 14 1 0 0 0 f f f t f i s 2 0 1082 "23 1082" _null_ _null_ _null_ _null_ _null_ "select $2 + $1" _null_ _null_ _null_ )
+insert ( 2556 pg_tablespace_databases 11 10 12 1 1000 0 0 f f f t t s s 1 0 26 26 _null_ _null_ _null_ _null_ _null_ pg_tablespace_databases _null_ _null_ _null_ )
+insert ( 2557 bool 11 10 12 1 0 0 0 f f f t f i s 1 0 16 23 _null_ _null_ _null_ _null_ _null_ int4_bool _null_ _null_ _null_ )
+insert ( 2558 int4 11 10 12 1 0 0 0 f f f t f i s 1 0 23 16 _null_ _null_ _null_ _null_ _null_ bool_int4 _null_ _null_ _null_ )
+insert ( 2559 lastval 11 10 12 1 0 0 0 f f f t f v u 0 0 20 "" _null_ _null_ _null_ _null_ _null_ lastval _null_ _null_ _null_ )
+insert ( 2560 pg_postmaster_start_time 11 10 12 1 0 0 0 f f f t f s s 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ pg_postmaster_start_time _null_ _null_ _null_ )
+insert ( 2034 pg_conf_load_time 11 10 12 1 0 0 0 f f f t f s r 0 0 1184 "" _null_ _null_ _null_ _null_ _null_ pg_conf_load_time _null_ _null_ _null_ )
+insert ( 2562 box_below 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_below _null_ _null_ _null_ )
+insert ( 2563 box_overbelow 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_overbelow _null_ _null_ _null_ )
+insert ( 2564 box_overabove 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_overabove _null_ _null_ _null_ )
+insert ( 2565 box_above 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_above _null_ _null_ _null_ )
+insert ( 2566 poly_below 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_below _null_ _null_ _null_ )
+insert ( 2567 poly_overbelow 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_overbelow _null_ _null_ _null_ )
+insert ( 2568 poly_overabove 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_overabove _null_ _null_ _null_ )
+insert ( 2569 poly_above 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "604 604" _null_ _null_ _null_ _null_ _null_ poly_above _null_ _null_ _null_ )
+insert ( 2587 circle_overbelow 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_overbelow _null_ _null_ _null_ )
+insert ( 2588 circle_overabove 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "718 718" _null_ _null_ _null_ _null_ _null_ circle_overabove _null_ _null_ _null_ )
+insert ( 2578 gist_box_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 603 21 26 2281" _null_ _null_ _null_ _null_ _null_ gist_box_consistent _null_ _null_ _null_ )
+insert ( 2581 gist_box_penalty 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gist_box_penalty _null_ _null_ _null_ )
+insert ( 2582 gist_box_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ gist_box_picksplit _null_ _null_ _null_ )
+insert ( 2583 gist_box_union 11 10 12 1 0 0 0 f f f t f i s 2 0 603 "2281 2281" _null_ _null_ _null_ _null_ _null_ gist_box_union _null_ _null_ _null_ )
+insert ( 2584 gist_box_same 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "603 603 2281" _null_ _null_ _null_ _null_ _null_ gist_box_same _null_ _null_ _null_ )
+insert ( 3998 gist_box_distance 11 10 12 1 0 0 0 f f f t f i s 5 0 701 "2281 603 21 26 2281" _null_ _null_ _null_ _null_ _null_ gist_box_distance _null_ _null_ _null_ )
+insert ( 2585 gist_poly_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 604 21 26 2281" _null_ _null_ _null_ _null_ _null_ gist_poly_consistent _null_ _null_ _null_ )
+insert ( 2586 gist_poly_compress 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ gist_poly_compress _null_ _null_ _null_ )
+insert ( 2591 gist_circle_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 718 21 26 2281" _null_ _null_ _null_ _null_ _null_ gist_circle_consistent _null_ _null_ _null_ )
+insert ( 2592 gist_circle_compress 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ gist_circle_compress _null_ _null_ _null_ )
+insert ( 1030 gist_point_compress 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ gist_point_compress _null_ _null_ _null_ )
+insert ( 3282 gist_point_fetch 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ gist_point_fetch _null_ _null_ _null_ )
+insert ( 2179 gist_point_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 600 21 26 2281" _null_ _null_ _null_ _null_ _null_ gist_point_consistent _null_ _null_ _null_ )
+insert ( 3064 gist_point_distance 11 10 12 1 0 0 0 f f f t f i s 5 0 701 "2281 600 21 26 2281" _null_ _null_ _null_ _null_ _null_ gist_point_distance _null_ _null_ _null_ )
+insert ( 3280 gist_circle_distance 11 10 12 1 0 0 0 f f f t f i s 5 0 701 "2281 718 21 26 2281" _null_ _null_ _null_ _null_ _null_ gist_circle_distance _null_ _null_ _null_ )
+insert ( 3288 gist_poly_distance 11 10 12 1 0 0 0 f f f t f i s 5 0 701 "2281 604 21 26 2281" _null_ _null_ _null_ _null_ _null_ gist_poly_distance _null_ _null_ _null_ )
+insert ( 2743 ginarrayextract 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "2277 2281 2281" _null_ _null_ _null_ _null_ _null_ ginarrayextract _null_ _null_ _null_ )
+insert ( 2774 ginqueryarrayextract 11 10 12 1 0 0 0 f f f t f i s 7 0 2281 "2277 2281 21 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ ginqueryarrayextract _null_ _null_ _null_ )
+insert ( 2744 ginarrayconsistent 11 10 12 1 0 0 0 f f f t f i s 8 0 16 "2281 21 2277 23 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ ginarrayconsistent _null_ _null_ _null_ )
+insert ( 3920 ginarraytriconsistent 11 10 12 1 0 0 0 f f f t f i s 7 0 18 "2281 21 2277 23 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ ginarraytriconsistent _null_ _null_ _null_ )
+insert ( 3076 ginarrayextract 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "2277 2281" _null_ _null_ _null_ _null_ _null_ ginarrayextract_2args _null_ _null_ _null_ )
+insert ( 2747 arrayoverlap 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2277 2277" _null_ _null_ _null_ _null_ _null_ arrayoverlap _null_ _null_ _null_ )
+insert ( 2748 arraycontains 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2277 2277" _null_ _null_ _null_ _null_ _null_ arraycontains _null_ _null_ _null_ )
+insert ( 2749 arraycontained 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2277 2277" _null_ _null_ _null_ _null_ _null_ arraycontained _null_ _null_ _null_ )
+insert ( 3383 brin_minmax_opcinfo 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ brin_minmax_opcinfo _null_ _null_ _null_ )
+insert ( 3384 brin_minmax_add_value 11 10 12 1 0 0 0 f f f t f i s 4 0 16 "2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ brin_minmax_add_value _null_ _null_ _null_ )
+insert ( 3385 brin_minmax_consistent 11 10 12 1 0 0 0 f f f t f i s 3 0 16 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ brin_minmax_consistent _null_ _null_ _null_ )
+insert ( 3386 brin_minmax_union 11 10 12 1 0 0 0 f f f t f i s 3 0 16 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ brin_minmax_union _null_ _null_ _null_ )
+insert ( 4105 brin_inclusion_opcinfo 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ brin_inclusion_opcinfo _null_ _null_ _null_ )
+insert ( 4106 brin_inclusion_add_value 11 10 12 1 0 0 0 f f f t f i s 4 0 16 "2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ brin_inclusion_add_value _null_ _null_ _null_ )
+insert ( 4107 brin_inclusion_consistent 11 10 12 1 0 0 0 f f f t f i s 3 0 16 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ brin_inclusion_consistent _null_ _null_ _null_ )
+insert ( 4108 brin_inclusion_union 11 10 12 1 0 0 0 f f f t f i s 3 0 16 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ brin_inclusion_union _null_ _null_ _null_ )
+insert ( 2880 pg_advisory_lock 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 20 _null_ _null_ _null_ _null_ _null_ pg_advisory_lock_int8 _null_ _null_ _null_ )
+insert ( 3089 pg_advisory_xact_lock 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 20 _null_ _null_ _null_ _null_ _null_ pg_advisory_xact_lock_int8 _null_ _null_ _null_ )
+insert ( 2881 pg_advisory_lock_shared 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 20 _null_ _null_ _null_ _null_ _null_ pg_advisory_lock_shared_int8 _null_ _null_ _null_ )
+insert ( 3090 pg_advisory_xact_lock_shared 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 20 _null_ _null_ _null_ _null_ _null_ pg_advisory_xact_lock_shared_int8 _null_ _null_ _null_ )
+insert ( 2882 pg_try_advisory_lock 11 10 12 1 0 0 0 f f f t f v r 1 0 16 20 _null_ _null_ _null_ _null_ _null_ pg_try_advisory_lock_int8 _null_ _null_ _null_ )
+insert ( 3091 pg_try_advisory_xact_lock 11 10 12 1 0 0 0 f f f t f v r 1 0 16 20 _null_ _null_ _null_ _null_ _null_ pg_try_advisory_xact_lock_int8 _null_ _null_ _null_ )
+insert ( 2883 pg_try_advisory_lock_shared 11 10 12 1 0 0 0 f f f t f v r 1 0 16 20 _null_ _null_ _null_ _null_ _null_ pg_try_advisory_lock_shared_int8 _null_ _null_ _null_ )
+insert ( 3092 pg_try_advisory_xact_lock_shared 11 10 12 1 0 0 0 f f f t f v r 1 0 16 20 _null_ _null_ _null_ _null_ _null_ pg_try_advisory_xact_lock_shared_int8 _null_ _null_ _null_ )
+insert ( 2884 pg_advisory_unlock 11 10 12 1 0 0 0 f f f t f v r 1 0 16 20 _null_ _null_ _null_ _null_ _null_ pg_advisory_unlock_int8 _null_ _null_ _null_ )
+insert ( 2885 pg_advisory_unlock_shared 11 10 12 1 0 0 0 f f f t f v r 1 0 16 20 _null_ _null_ _null_ _null_ _null_ pg_advisory_unlock_shared_int8 _null_ _null_ _null_ )
+insert ( 2886 pg_advisory_lock 11 10 12 1 0 0 0 f f f t f v r 2 0 2278 "23 23" _null_ _null_ _null_ _null_ _null_ pg_advisory_lock_int4 _null_ _null_ _null_ )
+insert ( 3093 pg_advisory_xact_lock 11 10 12 1 0 0 0 f f f t f v r 2 0 2278 "23 23" _null_ _null_ _null_ _null_ _null_ pg_advisory_xact_lock_int4 _null_ _null_ _null_ )
+insert ( 2887 pg_advisory_lock_shared 11 10 12 1 0 0 0 f f f t f v r 2 0 2278 "23 23" _null_ _null_ _null_ _null_ _null_ pg_advisory_lock_shared_int4 _null_ _null_ _null_ )
+insert ( 3094 pg_advisory_xact_lock_shared 11 10 12 1 0 0 0 f f f t f v r 2 0 2278 "23 23" _null_ _null_ _null_ _null_ _null_ pg_advisory_xact_lock_shared_int4 _null_ _null_ _null_ )
+insert ( 2888 pg_try_advisory_lock 11 10 12 1 0 0 0 f f f t f v r 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ pg_try_advisory_lock_int4 _null_ _null_ _null_ )
+insert ( 3095 pg_try_advisory_xact_lock 11 10 12 1 0 0 0 f f f t f v r 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ pg_try_advisory_xact_lock_int4 _null_ _null_ _null_ )
+insert ( 2889 pg_try_advisory_lock_shared 11 10 12 1 0 0 0 f f f t f v r 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ pg_try_advisory_lock_shared_int4 _null_ _null_ _null_ )
+insert ( 3096 pg_try_advisory_xact_lock_shared 11 10 12 1 0 0 0 f f f t f v r 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ pg_try_advisory_xact_lock_shared_int4 _null_ _null_ _null_ )
+insert ( 2890 pg_advisory_unlock 11 10 12 1 0 0 0 f f f t f v r 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ pg_advisory_unlock_int4 _null_ _null_ _null_ )
+insert ( 2891 pg_advisory_unlock_shared 11 10 12 1 0 0 0 f f f t f v r 2 0 16 "23 23" _null_ _null_ _null_ _null_ _null_ pg_advisory_unlock_shared_int4 _null_ _null_ _null_ )
+insert ( 2892 pg_advisory_unlock_all 11 10 12 1 0 0 0 f f f t f v r 0 0 2278 "" _null_ _null_ _null_ _null_ _null_ pg_advisory_unlock_all _null_ _null_ _null_ )
+insert ( 2893 xml_in 11 10 12 1 0 0 0 f f f t f s s 1 0 142 2275 _null_ _null_ _null_ _null_ _null_ xml_in _null_ _null_ _null_ )
+insert ( 2894 xml_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 142 _null_ _null_ _null_ _null_ _null_ xml_out _null_ _null_ _null_ )
+insert ( 2895 xmlcomment 11 10 12 1 0 0 0 f f f t f i s 1 0 142 25 _null_ _null_ _null_ _null_ _null_ xmlcomment _null_ _null_ _null_ )
+insert ( 2896 xml 11 10 12 1 0 0 0 f f f t f s s 1 0 142 25 _null_ _null_ _null_ _null_ _null_ texttoxml _null_ _null_ _null_ )
+insert ( 2897 xmlvalidate 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "142 25" _null_ _null_ _null_ _null_ _null_ xmlvalidate _null_ _null_ _null_ )
+insert ( 2898 xml_recv 11 10 12 1 0 0 0 f f f t f s s 1 0 142 2281 _null_ _null_ _null_ _null_ _null_ xml_recv _null_ _null_ _null_ )
+insert ( 2899 xml_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 142 _null_ _null_ _null_ _null_ _null_ xml_send _null_ _null_ _null_ )
+insert ( 2900 xmlconcat2 11 10 12 1 0 0 0 f f f f f i s 2 0 142 "142 142" _null_ _null_ _null_ _null_ _null_ xmlconcat2 _null_ _null_ _null_ )
+insert ( 2901 xmlagg 11 10 12 1 0 0 0 a f f f f i s 1 0 142 142 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 2922 text 11 10 12 1 0 0 0 f f f t f i s 1 0 25 142 _null_ _null_ _null_ _null_ _null_ xmltotext _null_ _null_ _null_ )
+insert ( 2923 table_to_xml 11 10 12 100 0 0 0 f f f t f s r 4 0 142 "2205 16 16 25" _null_ _null_ "{tbl,nulls,tableforest,targetns}" _null_ _null_ table_to_xml _null_ _null_ _null_ )
+insert ( 2924 query_to_xml 11 10 12 100 0 0 0 f f f t f v u 4 0 142 "25 16 16 25" _null_ _null_ "{query,nulls,tableforest,targetns}" _null_ _null_ query_to_xml _null_ _null_ _null_ )
+insert ( 2925 cursor_to_xml 11 10 12 100 0 0 0 f f f t f v u 5 0 142 "1790 23 16 16 25" _null_ _null_ "{cursor,count,nulls,tableforest,targetns}" _null_ _null_ cursor_to_xml _null_ _null_ _null_ )
+insert ( 2926 table_to_xmlschema 11 10 12 100 0 0 0 f f f t f s r 4 0 142 "2205 16 16 25" _null_ _null_ "{tbl,nulls,tableforest,targetns}" _null_ _null_ table_to_xmlschema _null_ _null_ _null_ )
+insert ( 2927 query_to_xmlschema 11 10 12 100 0 0 0 f f f t f v u 4 0 142 "25 16 16 25" _null_ _null_ "{query,nulls,tableforest,targetns}" _null_ _null_ query_to_xmlschema _null_ _null_ _null_ )
+insert ( 2928 cursor_to_xmlschema 11 10 12 100 0 0 0 f f f t f v u 4 0 142 "1790 16 16 25" _null_ _null_ "{cursor,nulls,tableforest,targetns}" _null_ _null_ cursor_to_xmlschema _null_ _null_ _null_ )
+insert ( 2929 table_to_xml_and_xmlschema 11 10 12 100 0 0 0 f f f t f s r 4 0 142 "2205 16 16 25" _null_ _null_ "{tbl,nulls,tableforest,targetns}" _null_ _null_ table_to_xml_and_xmlschema _null_ _null_ _null_ )
+insert ( 2930 query_to_xml_and_xmlschema 11 10 12 100 0 0 0 f f f t f v u 4 0 142 "25 16 16 25" _null_ _null_ "{query,nulls,tableforest,targetns}" _null_ _null_ query_to_xml_and_xmlschema _null_ _null_ _null_ )
+insert ( 2933 schema_to_xml 11 10 12 100 0 0 0 f f f t f s r 4 0 142 "19 16 16 25" _null_ _null_ "{schema,nulls,tableforest,targetns}" _null_ _null_ schema_to_xml _null_ _null_ _null_ )
+insert ( 2934 schema_to_xmlschema 11 10 12 100 0 0 0 f f f t f s r 4 0 142 "19 16 16 25" _null_ _null_ "{schema,nulls,tableforest,targetns}" _null_ _null_ schema_to_xmlschema _null_ _null_ _null_ )
+insert ( 2935 schema_to_xml_and_xmlschema 11 10 12 100 0 0 0 f f f t f s r 4 0 142 "19 16 16 25" _null_ _null_ "{schema,nulls,tableforest,targetns}" _null_ _null_ schema_to_xml_and_xmlschema _null_ _null_ _null_ )
+insert ( 2936 database_to_xml 11 10 12 100 0 0 0 f f f t f s r 3 0 142 "16 16 25" _null_ _null_ "{nulls,tableforest,targetns}" _null_ _null_ database_to_xml _null_ _null_ _null_ )
+insert ( 2937 database_to_xmlschema 11 10 12 100 0 0 0 f f f t f s r 3 0 142 "16 16 25" _null_ _null_ "{nulls,tableforest,targetns}" _null_ _null_ database_to_xmlschema _null_ _null_ _null_ )
+insert ( 2938 database_to_xml_and_xmlschema 11 10 12 100 0 0 0 f f f t f s r 3 0 142 "16 16 25" _null_ _null_ "{nulls,tableforest,targetns}" _null_ _null_ database_to_xml_and_xmlschema _null_ _null_ _null_ )
+insert ( 2931 xpath 11 10 12 1 0 0 0 f f f t f i s 3 0 143 "25 142 1009" _null_ _null_ _null_ _null_ _null_ xpath _null_ _null_ _null_ )
+insert ( 2932 xpath 11 10 14 1 0 0 0 f f f t f i s 2 0 143 "25 142" _null_ _null_ _null_ _null_ _null_ "select pg_catalog.xpath($1, $2, ''{}''::pg_catalog.text[])" _null_ _null_ _null_ )
+insert ( 2614 xmlexists 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "25 142" _null_ _null_ _null_ _null_ _null_ xmlexists _null_ _null_ _null_ )
+insert ( 3049 xpath_exists 11 10 12 1 0 0 0 f f f t f i s 3 0 16 "25 142 1009" _null_ _null_ _null_ _null_ _null_ xpath_exists _null_ _null_ _null_ )
+insert ( 3050 xpath_exists 11 10 14 1 0 0 0 f f f t f i s 2 0 16 "25 142" _null_ _null_ _null_ _null_ _null_ "select pg_catalog.xpath_exists($1, $2, ''{}''::pg_catalog.text[])" _null_ _null_ _null_ )
+insert ( 3051 xml_is_well_formed 11 10 12 1 0 0 0 f f f t f s s 1 0 16 25 _null_ _null_ _null_ _null_ _null_ xml_is_well_formed _null_ _null_ _null_ )
+insert ( 3052 xml_is_well_formed_document 11 10 12 1 0 0 0 f f f t f i s 1 0 16 25 _null_ _null_ _null_ _null_ _null_ xml_is_well_formed_document _null_ _null_ _null_ )
+insert ( 3053 xml_is_well_formed_content 11 10 12 1 0 0 0 f f f t f i s 1 0 16 25 _null_ _null_ _null_ _null_ _null_ xml_is_well_formed_content _null_ _null_ _null_ )
+insert ( 321 json_in 11 10 12 1 0 0 0 f f f t f i s 1 0 114 2275 _null_ _null_ _null_ _null_ _null_ json_in _null_ _null_ _null_ )
+insert ( 322 json_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 114 _null_ _null_ _null_ _null_ _null_ json_out _null_ _null_ _null_ )
+insert ( 323 json_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 114 2281 _null_ _null_ _null_ _null_ _null_ json_recv _null_ _null_ _null_ )
+insert ( 324 json_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 114 _null_ _null_ _null_ _null_ _null_ json_send _null_ _null_ _null_ )
+insert ( 3153 array_to_json 11 10 12 1 0 0 0 f f f t f s s 1 0 114 2277 _null_ _null_ _null_ _null_ _null_ array_to_json _null_ _null_ _null_ )
+insert ( 3154 array_to_json 11 10 12 1 0 0 0 f f f t f s s 2 0 114 "2277 16" _null_ _null_ _null_ _null_ _null_ array_to_json_pretty _null_ _null_ _null_ )
+insert ( 3155 row_to_json 11 10 12 1 0 0 0 f f f t f s s 1 0 114 2249 _null_ _null_ _null_ _null_ _null_ row_to_json _null_ _null_ _null_ )
+insert ( 3156 row_to_json 11 10 12 1 0 0 0 f f f t f s s 2 0 114 "2249 16" _null_ _null_ _null_ _null_ _null_ row_to_json_pretty _null_ _null_ _null_ )
+insert ( 3173 json_agg_transfn 11 10 12 1 0 0 0 f f f f f s s 2 0 2281 "2281 2283" _null_ _null_ _null_ _null_ _null_ json_agg_transfn _null_ _null_ _null_ )
+insert ( 3174 json_agg_finalfn 11 10 12 1 0 0 0 f f f f f i s 1 0 114 2281 _null_ _null_ _null_ _null_ _null_ json_agg_finalfn _null_ _null_ _null_ )
+insert ( 3175 json_agg 11 10 12 1 0 0 0 a f f f f s s 1 0 114 2283 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3180 json_object_agg_transfn 11 10 12 1 0 0 0 f f f f f s s 3 0 2281 "2281 2276 2276" _null_ _null_ _null_ _null_ _null_ json_object_agg_transfn _null_ _null_ _null_ )
+insert ( 3196 json_object_agg_finalfn 11 10 12 1 0 0 0 f f f f f i s 1 0 114 2281 _null_ _null_ _null_ _null_ _null_ json_object_agg_finalfn _null_ _null_ _null_ )
+insert ( 3197 json_object_agg 11 10 12 1 0 0 0 a f f f f s s 2 0 114 "2276 2276" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3198 json_build_array 11 10 12 1 0 2276 0 f f f f f s s 1 0 114 2276 "{2276}" "{v}" _null_ _null_ _null_ json_build_array _null_ _null_ _null_ )
+insert ( 3199 json_build_array 11 10 12 1 0 0 0 f f f f f s s 0 0 114 "" _null_ _null_ _null_ _null_ _null_ json_build_array_noargs _null_ _null_ _null_ )
+insert ( 3200 json_build_object 11 10 12 1 0 2276 0 f f f f f s s 1 0 114 2276 "{2276}" "{v}" _null_ _null_ _null_ json_build_object _null_ _null_ _null_ )
+insert ( 3201 json_build_object 11 10 12 1 0 0 0 f f f f f s s 0 0 114 "" _null_ _null_ _null_ _null_ _null_ json_build_object_noargs _null_ _null_ _null_ )
+insert ( 3202 json_object 11 10 12 1 0 0 0 f f f t f i s 1 0 114 1009 _null_ _null_ _null_ _null_ _null_ json_object _null_ _null_ _null_ )
+insert ( 3203 json_object 11 10 12 1 0 0 0 f f f t f i s 2 0 114 "1009 1009" _null_ _null_ _null_ _null_ _null_ json_object_two_arg _null_ _null_ _null_ )
+insert ( 3176 to_json 11 10 12 1 0 0 0 f f f t f s s 1 0 114 2283 _null_ _null_ _null_ _null_ _null_ to_json _null_ _null_ _null_ )
+insert ( 3261 json_strip_nulls 11 10 12 1 0 0 0 f f f t f i s 1 0 114 114 _null_ _null_ _null_ _null_ _null_ json_strip_nulls _null_ _null_ _null_ )
+insert ( 3947 json_object_field 11 10 12 1 0 0 0 f f f t f i s 2 0 114 "114 25" _null_ _null_ "{from_json, field_name}" _null_ _null_ json_object_field _null_ _null_ _null_ )
+insert ( 3948 json_object_field_text 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "114 25" _null_ _null_ "{from_json, field_name}" _null_ _null_ json_object_field_text _null_ _null_ _null_ )
+insert ( 3949 json_array_element 11 10 12 1 0 0 0 f f f t f i s 2 0 114 "114 23" _null_ _null_ "{from_json, element_index}" _null_ _null_ json_array_element _null_ _null_ _null_ )
+insert ( 3950 json_array_element_text 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "114 23" _null_ _null_ "{from_json, element_index}" _null_ _null_ json_array_element_text _null_ _null_ _null_ )
+insert ( 3951 json_extract_path 11 10 12 1 0 25 0 f f f t f i s 2 0 114 "114 1009" "{114,1009}" "{i,v}" "{from_json,path_elems}" _null_ _null_ json_extract_path _null_ _null_ _null_ )
+insert ( 3953 json_extract_path_text 11 10 12 1 0 25 0 f f f t f i s 2 0 25 "114 1009" "{114,1009}" "{i,v}" "{from_json,path_elems}" _null_ _null_ json_extract_path_text _null_ _null_ _null_ )
+insert ( 3955 json_array_elements 11 10 12 1 100 0 0 f f f t t i s 1 0 114 114 "{114,114}" "{i,o}" "{from_json,value}" _null_ _null_ json_array_elements _null_ _null_ _null_ )
+insert ( 3969 json_array_elements_text 11 10 12 1 100 0 0 f f f t t i s 1 0 25 114 "{114,25}" "{i,o}" "{from_json,value}" _null_ _null_ json_array_elements_text _null_ _null_ _null_ )
+insert ( 3956 json_array_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 114 _null_ _null_ _null_ _null_ _null_ json_array_length _null_ _null_ _null_ )
+insert ( 3957 json_object_keys 11 10 12 1 100 0 0 f f f t t i s 1 0 25 114 _null_ _null_ _null_ _null_ _null_ json_object_keys _null_ _null_ _null_ )
+insert ( 3958 json_each 11 10 12 1 100 0 0 f f f t t i s 1 0 2249 114 "{114,25,114}" "{i,o,o}" "{from_json,key,value}" _null_ _null_ json_each _null_ _null_ _null_ )
+insert ( 3959 json_each_text 11 10 12 1 100 0 0 f f f t t i s 1 0 2249 114 "{114,25,25}" "{i,o,o}" "{from_json,key,value}" _null_ _null_ json_each_text _null_ _null_ _null_ )
+insert ( 3960 json_populate_record 11 10 12 1 0 0 0 f f f f f s s 3 0 2283 "2283 114 16" _null_ _null_ _null_ _null_ _null_ json_populate_record _null_ _null_ _null_ )
+insert ( 3961 json_populate_recordset 11 10 12 1 100 0 0 f f f f t s s 3 0 2283 "2283 114 16" _null_ _null_ _null_ _null_ _null_ json_populate_recordset _null_ _null_ _null_ )
+insert ( 3204 json_to_record 11 10 12 1 0 0 0 f f f t f s s 1 0 2249 114 _null_ _null_ _null_ _null_ _null_ json_to_record _null_ _null_ _null_ )
+insert ( 3205 json_to_recordset 11 10 12 1 100 0 0 f f f f t s s 1 0 2249 114 _null_ _null_ _null_ _null_ _null_ json_to_recordset _null_ _null_ _null_ )
+insert ( 3968 json_typeof 11 10 12 1 0 0 0 f f f t f i s 1 0 25 114 _null_ _null_ _null_ _null_ _null_ json_typeof _null_ _null_ _null_ )
+insert ( 2952 uuid_in 11 10 12 1 0 0 0 f f f t f i s 1 0 2950 2275 _null_ _null_ _null_ _null_ _null_ uuid_in _null_ _null_ _null_ )
+insert ( 2953 uuid_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2950 _null_ _null_ _null_ _null_ _null_ uuid_out _null_ _null_ _null_ )
+insert ( 2954 uuid_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "2950 2950" _null_ _null_ _null_ _null_ _null_ uuid_lt _null_ _null_ _null_ )
+insert ( 2955 uuid_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "2950 2950" _null_ _null_ _null_ _null_ _null_ uuid_le _null_ _null_ _null_ )
+insert ( 2956 uuid_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "2950 2950" _null_ _null_ _null_ _null_ _null_ uuid_eq _null_ _null_ _null_ )
+insert ( 2957 uuid_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "2950 2950" _null_ _null_ _null_ _null_ _null_ uuid_ge _null_ _null_ _null_ )
+insert ( 2958 uuid_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "2950 2950" _null_ _null_ _null_ _null_ _null_ uuid_gt _null_ _null_ _null_ )
+insert ( 2959 uuid_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "2950 2950" _null_ _null_ _null_ _null_ _null_ uuid_ne _null_ _null_ _null_ )
+insert ( 2960 uuid_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "2950 2950" _null_ _null_ _null_ _null_ _null_ uuid_cmp _null_ _null_ _null_ )
+insert ( 3300 uuid_sortsupport 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ uuid_sortsupport _null_ _null_ _null_ )
+insert ( 2961 uuid_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 2950 2281 _null_ _null_ _null_ _null_ _null_ uuid_recv _null_ _null_ _null_ )
+insert ( 2962 uuid_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2950 _null_ _null_ _null_ _null_ _null_ uuid_send _null_ _null_ _null_ )
+insert ( 2963 uuid_hash 11 10 12 1 0 0 0 f f f t f i s 1 0 23 2950 _null_ _null_ _null_ _null_ _null_ uuid_hash _null_ _null_ _null_ )
+insert ( 3412 uuid_hash_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "2950 20" _null_ _null_ _null_ _null_ _null_ uuid_hash_extended _null_ _null_ _null_ )
+insert ( 3432 gen_random_uuid 11 10 12 1 0 0 0 f f t t f v s 0 0 2950 "" _null_ _null_ _null_ _null_ _null_ gen_random_uuid _null_ _null_ _null_ )
+insert ( 3229 pg_lsn_in 11 10 12 1 0 0 0 f f f t f i s 1 0 3220 2275 _null_ _null_ _null_ _null_ _null_ pg_lsn_in _null_ _null_ _null_ )
+insert ( 3230 pg_lsn_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3220 _null_ _null_ _null_ _null_ _null_ pg_lsn_out _null_ _null_ _null_ )
+insert ( 3231 pg_lsn_lt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_lt _null_ _null_ _null_ )
+insert ( 3232 pg_lsn_le 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_le _null_ _null_ _null_ )
+insert ( 3233 pg_lsn_eq 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_eq _null_ _null_ _null_ )
+insert ( 3234 pg_lsn_ge 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_ge _null_ _null_ _null_ )
+insert ( 3235 pg_lsn_gt 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_gt _null_ _null_ _null_ )
+insert ( 3236 pg_lsn_ne 11 10 12 1 0 0 0 f f t t f i s 2 0 16 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_ne _null_ _null_ _null_ )
+insert ( 3237 pg_lsn_mi 11 10 12 1 0 0 0 f f f t f i s 2 0 1700 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_mi _null_ _null_ _null_ )
+insert ( 3238 pg_lsn_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 3220 2281 _null_ _null_ _null_ _null_ _null_ pg_lsn_recv _null_ _null_ _null_ )
+insert ( 3239 pg_lsn_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 3220 _null_ _null_ _null_ _null_ _null_ pg_lsn_send _null_ _null_ _null_ )
+insert ( 3251 pg_lsn_cmp 11 10 12 1 0 0 0 f f t t f i s 2 0 23 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_cmp _null_ _null_ _null_ )
+insert ( 3252 pg_lsn_hash 11 10 12 1 0 0 0 f f f t f i s 1 0 23 3220 _null_ _null_ _null_ _null_ _null_ pg_lsn_hash _null_ _null_ _null_ )
+insert ( 3413 pg_lsn_hash_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "3220 20" _null_ _null_ _null_ _null_ _null_ pg_lsn_hash_extended _null_ _null_ _null_ )
+insert ( 4187 pg_lsn_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 3220 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_larger _null_ _null_ _null_ )
+insert ( 4188 pg_lsn_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 3220 "3220 3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_smaller _null_ _null_ _null_ )
+insert ( 3504 anyenum_in 11 10 12 1 0 0 0 f f f t f i s 1 0 3500 2275 _null_ _null_ _null_ _null_ _null_ anyenum_in _null_ _null_ _null_ )
+insert ( 3505 anyenum_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 3500 _null_ _null_ _null_ _null_ _null_ anyenum_out _null_ _null_ _null_ )
+insert ( 3506 enum_in 11 10 12 1 0 0 0 f f f t f s s 2 0 3500 "2275 26" _null_ _null_ _null_ _null_ _null_ enum_in _null_ _null_ _null_ )
+insert ( 3507 enum_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 3500 _null_ _null_ _null_ _null_ _null_ enum_out _null_ _null_ _null_ )
+insert ( 3508 enum_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_eq _null_ _null_ _null_ )
+insert ( 3509 enum_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_ne _null_ _null_ _null_ )
+insert ( 3510 enum_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_lt _null_ _null_ _null_ )
+insert ( 3511 enum_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_gt _null_ _null_ _null_ )
+insert ( 3512 enum_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_le _null_ _null_ _null_ )
+insert ( 3513 enum_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_ge _null_ _null_ _null_ )
+insert ( 3514 enum_cmp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_cmp _null_ _null_ _null_ )
+insert ( 3515 hashenum 11 10 12 1 0 0 0 f f f t f i s 1 0 23 3500 _null_ _null_ _null_ _null_ _null_ hashenum _null_ _null_ _null_ )
+insert ( 3414 hashenumextended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "3500 20" _null_ _null_ _null_ _null_ _null_ hashenumextended _null_ _null_ _null_ )
+insert ( 3524 enum_smaller 11 10 12 1 0 0 0 f f f t f i s 2 0 3500 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_smaller _null_ _null_ _null_ )
+insert ( 3525 enum_larger 11 10 12 1 0 0 0 f f f t f i s 2 0 3500 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_larger _null_ _null_ _null_ )
+insert ( 3526 max 11 10 12 1 0 0 0 a f f f f i s 1 0 3500 3500 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3527 min 11 10 12 1 0 0 0 a f f f f i s 1 0 3500 3500 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3528 enum_first 11 10 12 1 0 0 0 f f f f f s s 1 0 3500 3500 _null_ _null_ _null_ _null_ _null_ enum_first _null_ _null_ _null_ )
+insert ( 3529 enum_last 11 10 12 1 0 0 0 f f f f f s s 1 0 3500 3500 _null_ _null_ _null_ _null_ _null_ enum_last _null_ _null_ _null_ )
+insert ( 3530 enum_range 11 10 12 1 0 0 0 f f f f f s s 2 0 2277 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_range_bounds _null_ _null_ _null_ )
+insert ( 3531 enum_range 11 10 12 1 0 0 0 f f f f f s s 1 0 2277 3500 _null_ _null_ _null_ _null_ _null_ enum_range_all _null_ _null_ _null_ )
+insert ( 3532 enum_recv 11 10 12 1 0 0 0 f f f t f s s 2 0 3500 "2281 26" _null_ _null_ _null_ _null_ _null_ enum_recv _null_ _null_ _null_ )
+insert ( 3533 enum_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 3500 _null_ _null_ _null_ _null_ _null_ enum_send _null_ _null_ _null_ )
+insert ( 3610 tsvectorin 11 10 12 1 0 0 0 f f f t f i s 1 0 3614 2275 _null_ _null_ _null_ _null_ _null_ tsvectorin _null_ _null_ _null_ )
+insert ( 3639 tsvectorrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 3614 2281 _null_ _null_ _null_ _null_ _null_ tsvectorrecv _null_ _null_ _null_ )
+insert ( 3611 tsvectorout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3614 _null_ _null_ _null_ _null_ _null_ tsvectorout _null_ _null_ _null_ )
+insert ( 3638 tsvectorsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 3614 _null_ _null_ _null_ _null_ _null_ tsvectorsend _null_ _null_ _null_ )
+insert ( 3612 tsqueryin 11 10 12 1 0 0 0 f f f t f i s 1 0 3615 2275 _null_ _null_ _null_ _null_ _null_ tsqueryin _null_ _null_ _null_ )
+insert ( 3641 tsqueryrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 3615 2281 _null_ _null_ _null_ _null_ _null_ tsqueryrecv _null_ _null_ _null_ )
+insert ( 3613 tsqueryout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3615 _null_ _null_ _null_ _null_ _null_ tsqueryout _null_ _null_ _null_ )
+insert ( 3640 tsquerysend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 3615 _null_ _null_ _null_ _null_ _null_ tsquerysend _null_ _null_ _null_ )
+insert ( 3646 gtsvectorin 11 10 12 1 0 0 0 f f f t f i s 1 0 3642 2275 _null_ _null_ _null_ _null_ _null_ gtsvectorin _null_ _null_ _null_ )
+insert ( 3647 gtsvectorout 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3642 _null_ _null_ _null_ _null_ _null_ gtsvectorout _null_ _null_ _null_ )
+insert ( 3616 tsvector_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3614 3614" _null_ _null_ _null_ _null_ _null_ tsvector_lt _null_ _null_ _null_ )
+insert ( 3617 tsvector_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3614 3614" _null_ _null_ _null_ _null_ _null_ tsvector_le _null_ _null_ _null_ )
+insert ( 3618 tsvector_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3614 3614" _null_ _null_ _null_ _null_ _null_ tsvector_eq _null_ _null_ _null_ )
+insert ( 3619 tsvector_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3614 3614" _null_ _null_ _null_ _null_ _null_ tsvector_ne _null_ _null_ _null_ )
+insert ( 3620 tsvector_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3614 3614" _null_ _null_ _null_ _null_ _null_ tsvector_ge _null_ _null_ _null_ )
+insert ( 3621 tsvector_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3614 3614" _null_ _null_ _null_ _null_ _null_ tsvector_gt _null_ _null_ _null_ )
+insert ( 3622 tsvector_cmp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "3614 3614" _null_ _null_ _null_ _null_ _null_ tsvector_cmp _null_ _null_ _null_ )
+insert ( 3711 length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 3614 _null_ _null_ _null_ _null_ _null_ tsvector_length _null_ _null_ _null_ )
+insert ( 3623 strip 11 10 12 1 0 0 0 f f f t f i s 1 0 3614 3614 _null_ _null_ _null_ _null_ _null_ tsvector_strip _null_ _null_ _null_ )
+insert ( 3624 setweight 11 10 12 1 0 0 0 f f f t f i s 2 0 3614 "3614 18" _null_ _null_ _null_ _null_ _null_ tsvector_setweight _null_ _null_ _null_ )
+insert ( 3320 setweight 11 10 12 1 0 0 0 f f f t f i s 3 0 3614 "3614 18 1009" _null_ _null_ _null_ _null_ _null_ tsvector_setweight_by_filter _null_ _null_ _null_ )
+insert ( 3625 tsvector_concat 11 10 12 1 0 0 0 f f f t f i s 2 0 3614 "3614 3614" _null_ _null_ _null_ _null_ _null_ tsvector_concat _null_ _null_ _null_ )
+insert ( 3321 ts_delete 11 10 12 1 0 0 0 f f f t f i s 2 0 3614 "3614 25" _null_ _null_ _null_ _null_ _null_ tsvector_delete_str _null_ _null_ _null_ )
+insert ( 3323 ts_delete 11 10 12 1 0 0 0 f f f t f i s 2 0 3614 "3614 1009" _null_ _null_ _null_ _null_ _null_ tsvector_delete_arr _null_ _null_ _null_ )
+insert ( 3322 unnest 11 10 12 1 10 0 0 f f f t t i s 1 0 2249 3614 "{3614,25,1005,1009}" "{i,o,o,o}" "{tsvector,lexeme,positions,weights}" _null_ _null_ tsvector_unnest _null_ _null_ _null_ )
+insert ( 3326 tsvector_to_array 11 10 12 1 0 0 0 f f f t f i s 1 0 1009 3614 _null_ _null_ _null_ _null_ _null_ tsvector_to_array _null_ _null_ _null_ )
+insert ( 3327 array_to_tsvector 11 10 12 1 0 0 0 f f f t f i s 1 0 3614 1009 _null_ _null_ _null_ _null_ _null_ array_to_tsvector _null_ _null_ _null_ )
+insert ( 3319 ts_filter 11 10 12 1 0 0 0 f f f t f i s 2 0 3614 "3614 1002" _null_ _null_ _null_ _null_ _null_ tsvector_filter _null_ _null_ _null_ )
+insert ( 3634 ts_match_vq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3614 3615" _null_ _null_ _null_ _null_ _null_ ts_match_vq _null_ _null_ _null_ )
+insert ( 3635 ts_match_qv 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3615 3614" _null_ _null_ _null_ _null_ _null_ ts_match_qv _null_ _null_ _null_ )
+insert ( 3760 ts_match_tt 11 10 12 100 0 0 0 f f f t f s s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ ts_match_tt _null_ _null_ _null_ )
+insert ( 3761 ts_match_tq 11 10 12 100 0 0 0 f f f t f s s 2 0 16 "25 3615" _null_ _null_ _null_ _null_ _null_ ts_match_tq _null_ _null_ _null_ )
+insert ( 3648 gtsvector_compress 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ gtsvector_compress _null_ _null_ _null_ )
+insert ( 3649 gtsvector_decompress 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ gtsvector_decompress _null_ _null_ _null_ )
+insert ( 3650 gtsvector_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ gtsvector_picksplit _null_ _null_ _null_ )
+insert ( 3651 gtsvector_union 11 10 12 1 0 0 0 f f f t f i s 2 0 3642 "2281 2281" _null_ _null_ _null_ _null_ _null_ gtsvector_union _null_ _null_ _null_ )
+insert ( 3652 gtsvector_same 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "3642 3642 2281" _null_ _null_ _null_ _null_ _null_ gtsvector_same _null_ _null_ _null_ )
+insert ( 3653 gtsvector_penalty 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gtsvector_penalty _null_ _null_ _null_ )
+insert ( 3654 gtsvector_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 3614 21 26 2281" _null_ _null_ _null_ _null_ _null_ gtsvector_consistent _null_ _null_ _null_ )
+insert ( 3790 gtsvector_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 3642 23 26 2281" _null_ _null_ _null_ _null_ _null_ gtsvector_consistent_oldsig _null_ _null_ _null_ )
+insert ( 3434 gtsvector_options 11 10 12 1 0 0 0 f f f f f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ gtsvector_options _null_ _null_ _null_ )
+insert ( 3656 gin_extract_tsvector 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "3614 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_extract_tsvector _null_ _null_ _null_ )
+insert ( 3657 gin_extract_tsquery 11 10 12 1 0 0 0 f f f t f i s 7 0 2281 "3614 2281 21 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_extract_tsquery _null_ _null_ _null_ )
+insert ( 3658 gin_tsquery_consistent 11 10 12 1 0 0 0 f f f t f i s 8 0 16 "2281 21 3614 23 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_tsquery_consistent _null_ _null_ _null_ )
+insert ( 3921 gin_tsquery_triconsistent 11 10 12 1 0 0 0 f f f t f i s 7 0 18 "2281 21 3614 23 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_tsquery_triconsistent _null_ _null_ _null_ )
+insert ( 3724 gin_cmp_tslexeme 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "25 25" _null_ _null_ _null_ _null_ _null_ gin_cmp_tslexeme _null_ _null_ _null_ )
+insert ( 2700 gin_cmp_prefix 11 10 12 1 0 0 0 f f f t f i s 4 0 23 "25 25 21 2281" _null_ _null_ _null_ _null_ _null_ gin_cmp_prefix _null_ _null_ _null_ )
+insert ( 3077 gin_extract_tsvector 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "3614 2281" _null_ _null_ _null_ _null_ _null_ gin_extract_tsvector_2args _null_ _null_ _null_ )
+insert ( 3087 gin_extract_tsquery 11 10 12 1 0 0 0 f f f t f i s 5 0 2281 "3615 2281 21 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_extract_tsquery_5args _null_ _null_ _null_ )
+insert ( 3088 gin_tsquery_consistent 11 10 12 1 0 0 0 f f f t f i s 6 0 16 "2281 21 3615 23 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_tsquery_consistent_6args _null_ _null_ _null_ )
+insert ( 3791 gin_extract_tsquery 11 10 12 1 0 0 0 f f f t f i s 7 0 2281 "3615 2281 21 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_extract_tsquery_oldsig _null_ _null_ _null_ )
+insert ( 3792 gin_tsquery_consistent 11 10 12 1 0 0 0 f f f t f i s 8 0 16 "2281 21 3615 23 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_tsquery_consistent_oldsig _null_ _null_ _null_ )
+insert ( 3789 gin_clean_pending_list 11 10 12 1 0 0 0 f f f t f v u 1 0 20 2205 _null_ _null_ _null_ _null_ _null_ gin_clean_pending_list _null_ _null_ _null_ )
+insert ( 3662 tsquery_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_lt _null_ _null_ _null_ )
+insert ( 3663 tsquery_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_le _null_ _null_ _null_ )
+insert ( 3664 tsquery_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_eq _null_ _null_ _null_ )
+insert ( 3665 tsquery_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_ne _null_ _null_ _null_ )
+insert ( 3666 tsquery_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_ge _null_ _null_ _null_ )
+insert ( 3667 tsquery_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_gt _null_ _null_ _null_ )
+insert ( 3668 tsquery_cmp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_cmp _null_ _null_ _null_ )
+insert ( 3669 tsquery_and 11 10 12 1 0 0 0 f f f t f i s 2 0 3615 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_and _null_ _null_ _null_ )
+insert ( 3670 tsquery_or 11 10 12 1 0 0 0 f f f t f i s 2 0 3615 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_or _null_ _null_ _null_ )
+insert ( 5003 tsquery_phrase 11 10 12 1 0 0 0 f f f t f i s 2 0 3615 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_phrase _null_ _null_ _null_ )
+insert ( 5004 tsquery_phrase 11 10 12 1 0 0 0 f f f t f i s 3 0 3615 "3615 3615 23" _null_ _null_ _null_ _null_ _null_ tsquery_phrase_distance _null_ _null_ _null_ )
+insert ( 3671 tsquery_not 11 10 12 1 0 0 0 f f f t f i s 1 0 3615 3615 _null_ _null_ _null_ _null_ _null_ tsquery_not _null_ _null_ _null_ )
+insert ( 3691 tsq_mcontains 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsq_mcontains _null_ _null_ _null_ )
+insert ( 3692 tsq_mcontained 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3615 3615" _null_ _null_ _null_ _null_ _null_ tsq_mcontained _null_ _null_ _null_ )
+insert ( 3672 numnode 11 10 12 1 0 0 0 f f f t f i s 1 0 23 3615 _null_ _null_ _null_ _null_ _null_ tsquery_numnode _null_ _null_ _null_ )
+insert ( 3673 querytree 11 10 12 1 0 0 0 f f f t f i s 1 0 25 3615 _null_ _null_ _null_ _null_ _null_ tsquerytree _null_ _null_ _null_ )
+insert ( 3684 ts_rewrite 11 10 12 1 0 0 0 f f f t f i s 3 0 3615 "3615 3615 3615" _null_ _null_ _null_ _null_ _null_ tsquery_rewrite _null_ _null_ _null_ )
+insert ( 3685 ts_rewrite 11 10 12 100 0 0 0 f f f t f v u 2 0 3615 "3615 25" _null_ _null_ _null_ _null_ _null_ tsquery_rewrite_query _null_ _null_ _null_ )
+insert ( 3695 gtsquery_compress 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ gtsquery_compress _null_ _null_ _null_ )
+insert ( 3697 gtsquery_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ gtsquery_picksplit _null_ _null_ _null_ )
+insert ( 3698 gtsquery_union 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "2281 2281" _null_ _null_ _null_ _null_ _null_ gtsquery_union _null_ _null_ _null_ )
+insert ( 3699 gtsquery_same 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "20 20 2281" _null_ _null_ _null_ _null_ _null_ gtsquery_same _null_ _null_ _null_ )
+insert ( 3700 gtsquery_penalty 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gtsquery_penalty _null_ _null_ _null_ )
+insert ( 3701 gtsquery_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 3615 21 26 2281" _null_ _null_ _null_ _null_ _null_ gtsquery_consistent _null_ _null_ _null_ )
+insert ( 3793 gtsquery_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 2281 23 26 2281" _null_ _null_ _null_ _null_ _null_ gtsquery_consistent_oldsig _null_ _null_ _null_ )
+insert ( 3686 tsmatchsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ tsmatchsel _null_ _null_ _null_ )
+insert ( 3687 tsmatchjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ tsmatchjoinsel _null_ _null_ _null_ )
+insert ( 3688 ts_typanalyze 11 10 12 1 0 0 0 f f f t f s s 1 0 16 2281 _null_ _null_ _null_ _null_ _null_ ts_typanalyze _null_ _null_ _null_ )
+insert ( 3689 ts_stat 11 10 12 10 10000 0 0 f f f t t v u 1 0 2249 25 "{25,25,23,23}" "{i,o,o,o}" "{query,word,ndoc,nentry}" _null_ _null_ ts_stat1 _null_ _null_ _null_ )
+insert ( 3690 ts_stat 11 10 12 10 10000 0 0 f f f t t v u 2 0 2249 "25 25" "{25,25,25,23,23}" "{i,i,o,o,o}" "{query,weights,word,ndoc,nentry}" _null_ _null_ ts_stat2 _null_ _null_ _null_ )
+insert ( 3703 ts_rank 11 10 12 1 0 0 0 f f f t f i s 4 0 700 "1021 3614 3615 23" _null_ _null_ _null_ _null_ _null_ ts_rank_wttf _null_ _null_ _null_ )
+insert ( 3704 ts_rank 11 10 12 1 0 0 0 f f f t f i s 3 0 700 "1021 3614 3615" _null_ _null_ _null_ _null_ _null_ ts_rank_wtt _null_ _null_ _null_ )
+insert ( 3705 ts_rank 11 10 12 1 0 0 0 f f f t f i s 3 0 700 "3614 3615 23" _null_ _null_ _null_ _null_ _null_ ts_rank_ttf _null_ _null_ _null_ )
+insert ( 3706 ts_rank 11 10 12 1 0 0 0 f f f t f i s 2 0 700 "3614 3615" _null_ _null_ _null_ _null_ _null_ ts_rank_tt _null_ _null_ _null_ )
+insert ( 3707 ts_rank_cd 11 10 12 1 0 0 0 f f f t f i s 4 0 700 "1021 3614 3615 23" _null_ _null_ _null_ _null_ _null_ ts_rankcd_wttf _null_ _null_ _null_ )
+insert ( 3708 ts_rank_cd 11 10 12 1 0 0 0 f f f t f i s 3 0 700 "1021 3614 3615" _null_ _null_ _null_ _null_ _null_ ts_rankcd_wtt _null_ _null_ _null_ )
+insert ( 3709 ts_rank_cd 11 10 12 1 0 0 0 f f f t f i s 3 0 700 "3614 3615 23" _null_ _null_ _null_ _null_ _null_ ts_rankcd_ttf _null_ _null_ _null_ )
+insert ( 3710 ts_rank_cd 11 10 12 1 0 0 0 f f f t f i s 2 0 700 "3614 3615" _null_ _null_ _null_ _null_ _null_ ts_rankcd_tt _null_ _null_ _null_ )
+insert ( 3713 ts_token_type 11 10 12 1 16 0 0 f f f t t i s 1 0 2249 26 "{26,23,25,25}" "{i,o,o,o}" "{parser_oid,tokid,alias,description}" _null_ _null_ ts_token_type_byid _null_ _null_ _null_ )
+insert ( 3714 ts_token_type 11 10 12 1 16 0 0 f f f t t s s 1 0 2249 25 "{25,23,25,25}" "{i,o,o,o}" "{parser_name,tokid,alias,description}" _null_ _null_ ts_token_type_byname _null_ _null_ _null_ )
+insert ( 3715 ts_parse 11 10 12 1 1000 0 0 f f f t t i s 2 0 2249 "26 25" "{26,25,23,25}" "{i,i,o,o}" "{parser_oid,txt,tokid,token}" _null_ _null_ ts_parse_byid _null_ _null_ _null_ )
+insert ( 3716 ts_parse 11 10 12 1 1000 0 0 f f f t t s s 2 0 2249 "25 25" "{25,25,23,25}" "{i,i,o,o}" "{parser_name,txt,tokid,token}" _null_ _null_ ts_parse_byname _null_ _null_ _null_ )
+insert ( 3717 prsd_start 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "2281 23" _null_ _null_ _null_ _null_ _null_ prsd_start _null_ _null_ _null_ )
+insert ( 3718 prsd_nexttoken 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ prsd_nexttoken _null_ _null_ _null_ )
+insert ( 3719 prsd_end 11 10 12 1 0 0 0 f f f t f i s 1 0 2278 2281 _null_ _null_ _null_ _null_ _null_ prsd_end _null_ _null_ _null_ )
+insert ( 3720 prsd_headline 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "2281 2281 3615" _null_ _null_ _null_ _null_ _null_ prsd_headline _null_ _null_ _null_ )
+insert ( 3721 prsd_lextype 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ prsd_lextype _null_ _null_ _null_ )
+insert ( 3723 ts_lexize 11 10 12 1 0 0 0 f f f t f i s 2 0 1009 "3769 25" _null_ _null_ _null_ _null_ _null_ ts_lexize _null_ _null_ _null_ )
+insert ( 3725 dsimple_init 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ dsimple_init _null_ _null_ _null_ )
+insert ( 3726 dsimple_lexize 11 10 12 1 0 0 0 f f f t f i s 4 0 2281 "2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ dsimple_lexize _null_ _null_ _null_ )
+insert ( 3728 dsynonym_init 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ dsynonym_init _null_ _null_ _null_ )
+insert ( 3729 dsynonym_lexize 11 10 12 1 0 0 0 f f f t f i s 4 0 2281 "2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ dsynonym_lexize _null_ _null_ _null_ )
+insert ( 3731 dispell_init 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ dispell_init _null_ _null_ _null_ )
+insert ( 3732 dispell_lexize 11 10 12 1 0 0 0 f f f t f i s 4 0 2281 "2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ dispell_lexize _null_ _null_ _null_ )
+insert ( 3740 thesaurus_init 11 10 12 1 0 0 0 f f f t f i s 1 0 2281 2281 _null_ _null_ _null_ _null_ _null_ thesaurus_init _null_ _null_ _null_ )
+insert ( 3741 thesaurus_lexize 11 10 12 1 0 0 0 f f f t f i s 4 0 2281 "2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ thesaurus_lexize _null_ _null_ _null_ )
+insert ( 3743 ts_headline 11 10 12 100 0 0 0 f f f t f i s 4 0 25 "3734 25 3615 25" _null_ _null_ _null_ _null_ _null_ ts_headline_byid_opt _null_ _null_ _null_ )
+insert ( 3744 ts_headline 11 10 12 100 0 0 0 f f f t f i s 3 0 25 "3734 25 3615" _null_ _null_ _null_ _null_ _null_ ts_headline_byid _null_ _null_ _null_ )
+insert ( 3754 ts_headline 11 10 12 100 0 0 0 f f f t f s s 3 0 25 "25 3615 25" _null_ _null_ _null_ _null_ _null_ ts_headline_opt _null_ _null_ _null_ )
+insert ( 3755 ts_headline 11 10 12 100 0 0 0 f f f t f s s 2 0 25 "25 3615" _null_ _null_ _null_ _null_ _null_ ts_headline _null_ _null_ _null_ )
+insert ( 4201 ts_headline 11 10 12 100 0 0 0 f f f t f i s 4 0 3802 "3734 3802 3615 25" _null_ _null_ _null_ _null_ _null_ ts_headline_jsonb_byid_opt _null_ _null_ _null_ )
+insert ( 4202 ts_headline 11 10 12 100 0 0 0 f f f t f i s 3 0 3802 "3734 3802 3615" _null_ _null_ _null_ _null_ _null_ ts_headline_jsonb_byid _null_ _null_ _null_ )
+insert ( 4203 ts_headline 11 10 12 100 0 0 0 f f f t f s s 3 0 3802 "3802 3615 25" _null_ _null_ _null_ _null_ _null_ ts_headline_jsonb_opt _null_ _null_ _null_ )
+insert ( 4204 ts_headline 11 10 12 100 0 0 0 f f f t f s s 2 0 3802 "3802 3615" _null_ _null_ _null_ _null_ _null_ ts_headline_jsonb _null_ _null_ _null_ )
+insert ( 4205 ts_headline 11 10 12 100 0 0 0 f f f t f i s 4 0 114 "3734 114 3615 25" _null_ _null_ _null_ _null_ _null_ ts_headline_json_byid_opt _null_ _null_ _null_ )
+insert ( 4206 ts_headline 11 10 12 100 0 0 0 f f f t f i s 3 0 114 "3734 114 3615" _null_ _null_ _null_ _null_ _null_ ts_headline_json_byid _null_ _null_ _null_ )
+insert ( 4207 ts_headline 11 10 12 100 0 0 0 f f f t f s s 3 0 114 "114 3615 25" _null_ _null_ _null_ _null_ _null_ ts_headline_json_opt _null_ _null_ _null_ )
+insert ( 4208 ts_headline 11 10 12 100 0 0 0 f f f t f s s 2 0 114 "114 3615" _null_ _null_ _null_ _null_ _null_ ts_headline_json _null_ _null_ _null_ )
+insert ( 3745 to_tsvector 11 10 12 100 0 0 0 f f f t f i s 2 0 3614 "3734 25" _null_ _null_ _null_ _null_ _null_ to_tsvector_byid _null_ _null_ _null_ )
+insert ( 3746 to_tsquery 11 10 12 100 0 0 0 f f f t f i s 2 0 3615 "3734 25" _null_ _null_ _null_ _null_ _null_ to_tsquery_byid _null_ _null_ _null_ )
+insert ( 3747 plainto_tsquery 11 10 12 100 0 0 0 f f f t f i s 2 0 3615 "3734 25" _null_ _null_ _null_ _null_ _null_ plainto_tsquery_byid _null_ _null_ _null_ )
+insert ( 5006 phraseto_tsquery 11 10 12 100 0 0 0 f f f t f i s 2 0 3615 "3734 25" _null_ _null_ _null_ _null_ _null_ phraseto_tsquery_byid _null_ _null_ _null_ )
+insert ( 5007 websearch_to_tsquery 11 10 12 100 0 0 0 f f f t f i s 2 0 3615 "3734 25" _null_ _null_ _null_ _null_ _null_ websearch_to_tsquery_byid _null_ _null_ _null_ )
+insert ( 3749 to_tsvector 11 10 12 100 0 0 0 f f f t f s s 1 0 3614 25 _null_ _null_ _null_ _null_ _null_ to_tsvector _null_ _null_ _null_ )
+insert ( 3750 to_tsquery 11 10 12 100 0 0 0 f f f t f s s 1 0 3615 25 _null_ _null_ _null_ _null_ _null_ to_tsquery _null_ _null_ _null_ )
+insert ( 3751 plainto_tsquery 11 10 12 100 0 0 0 f f f t f s s 1 0 3615 25 _null_ _null_ _null_ _null_ _null_ plainto_tsquery _null_ _null_ _null_ )
+insert ( 5001 phraseto_tsquery 11 10 12 100 0 0 0 f f f t f s s 1 0 3615 25 _null_ _null_ _null_ _null_ _null_ phraseto_tsquery _null_ _null_ _null_ )
+insert ( 5009 websearch_to_tsquery 11 10 12 100 0 0 0 f f f t f s s 1 0 3615 25 _null_ _null_ _null_ _null_ _null_ websearch_to_tsquery _null_ _null_ _null_ )
+insert ( 4209 to_tsvector 11 10 12 100 0 0 0 f f f t f s s 1 0 3614 3802 _null_ _null_ _null_ _null_ _null_ jsonb_string_to_tsvector _null_ _null_ _null_ )
+insert ( 4213 jsonb_to_tsvector 11 10 12 100 0 0 0 f f f t f s s 2 0 3614 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_to_tsvector _null_ _null_ _null_ )
+insert ( 4210 to_tsvector 11 10 12 100 0 0 0 f f f t f s s 1 0 3614 114 _null_ _null_ _null_ _null_ _null_ json_string_to_tsvector _null_ _null_ _null_ )
+insert ( 4215 json_to_tsvector 11 10 12 100 0 0 0 f f f t f s s 2 0 3614 "114 3802" _null_ _null_ _null_ _null_ _null_ json_to_tsvector _null_ _null_ _null_ )
+insert ( 4211 to_tsvector 11 10 12 100 0 0 0 f f f t f i s 2 0 3614 "3734 3802" _null_ _null_ _null_ _null_ _null_ jsonb_string_to_tsvector_byid _null_ _null_ _null_ )
+insert ( 4214 jsonb_to_tsvector 11 10 12 100 0 0 0 f f f t f i s 3 0 3614 "3734 3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_to_tsvector_byid _null_ _null_ _null_ )
+insert ( 4212 to_tsvector 11 10 12 100 0 0 0 f f f t f i s 2 0 3614 "3734 114" _null_ _null_ _null_ _null_ _null_ json_string_to_tsvector_byid _null_ _null_ _null_ )
+insert ( 4216 json_to_tsvector 11 10 12 100 0 0 0 f f f t f i s 3 0 3614 "3734 114 3802" _null_ _null_ _null_ _null_ _null_ json_to_tsvector_byid _null_ _null_ _null_ )
+insert ( 3752 tsvector_update_trigger 11 10 12 1 0 0 0 f f f f f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ tsvector_update_trigger_byid _null_ _null_ _null_ )
+insert ( 3753 tsvector_update_trigger_column 11 10 12 1 0 0 0 f f f f f v s 0 0 2279 "" _null_ _null_ _null_ _null_ _null_ tsvector_update_trigger_bycolumn _null_ _null_ _null_ )
+insert ( 3759 get_current_ts_config 11 10 12 1 0 0 0 f f f t f s s 0 0 3734 "" _null_ _null_ _null_ _null_ _null_ get_current_ts_config _null_ _null_ _null_ )
+insert ( 3736 regconfigin 11 10 12 1 0 0 0 f f f t f s s 1 0 3734 2275 _null_ _null_ _null_ _null_ _null_ regconfigin _null_ _null_ _null_ )
+insert ( 3737 regconfigout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 3734 _null_ _null_ _null_ _null_ _null_ regconfigout _null_ _null_ _null_ )
+insert ( 3738 regconfigrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 3734 2281 _null_ _null_ _null_ _null_ _null_ regconfigrecv _null_ _null_ _null_ )
+insert ( 3739 regconfigsend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 3734 _null_ _null_ _null_ _null_ _null_ regconfigsend _null_ _null_ _null_ )
+insert ( 3771 regdictionaryin 11 10 12 1 0 0 0 f f f t f s s 1 0 3769 2275 _null_ _null_ _null_ _null_ _null_ regdictionaryin _null_ _null_ _null_ )
+insert ( 3772 regdictionaryout 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 3769 _null_ _null_ _null_ _null_ _null_ regdictionaryout _null_ _null_ _null_ )
+insert ( 3773 regdictionaryrecv 11 10 12 1 0 0 0 f f f t f i s 1 0 3769 2281 _null_ _null_ _null_ _null_ _null_ regdictionaryrecv _null_ _null_ _null_ )
+insert ( 3774 regdictionarysend 11 10 12 1 0 0 0 f f f t f i s 1 0 17 3769 _null_ _null_ _null_ _null_ _null_ regdictionarysend _null_ _null_ _null_ )
+insert ( 3806 jsonb_in 11 10 12 1 0 0 0 f f f t f i s 1 0 3802 2275 _null_ _null_ _null_ _null_ _null_ jsonb_in _null_ _null_ _null_ )
+insert ( 3805 jsonb_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 3802 2281 _null_ _null_ _null_ _null_ _null_ jsonb_recv _null_ _null_ _null_ )
+insert ( 3804 jsonb_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 3802 _null_ _null_ _null_ _null_ _null_ jsonb_out _null_ _null_ _null_ )
+insert ( 3803 jsonb_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 3802 _null_ _null_ _null_ _null_ _null_ jsonb_send _null_ _null_ _null_ )
+insert ( 3263 jsonb_object 11 10 12 1 0 0 0 f f f t f i s 1 0 3802 1009 _null_ _null_ _null_ _null_ _null_ jsonb_object _null_ _null_ _null_ )
+insert ( 3264 jsonb_object 11 10 12 1 0 0 0 f f f t f i s 2 0 3802 "1009 1009" _null_ _null_ _null_ _null_ _null_ jsonb_object_two_arg _null_ _null_ _null_ )
+insert ( 3787 to_jsonb 11 10 12 1 0 0 0 f f f t f s s 1 0 3802 2283 _null_ _null_ _null_ _null_ _null_ to_jsonb _null_ _null_ _null_ )
+insert ( 3265 jsonb_agg_transfn 11 10 12 1 0 0 0 f f f f f s s 2 0 2281 "2281 2283" _null_ _null_ _null_ _null_ _null_ jsonb_agg_transfn _null_ _null_ _null_ )
+insert ( 3266 jsonb_agg_finalfn 11 10 12 1 0 0 0 f f f f f s s 1 0 3802 2281 _null_ _null_ _null_ _null_ _null_ jsonb_agg_finalfn _null_ _null_ _null_ )
+insert ( 3267 jsonb_agg 11 10 12 1 0 0 0 a f f f f s s 1 0 3802 2283 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3268 jsonb_object_agg_transfn 11 10 12 1 0 0 0 f f f f f s s 3 0 2281 "2281 2276 2276" _null_ _null_ _null_ _null_ _null_ jsonb_object_agg_transfn _null_ _null_ _null_ )
+insert ( 3269 jsonb_object_agg_finalfn 11 10 12 1 0 0 0 f f f f f s s 1 0 3802 2281 _null_ _null_ _null_ _null_ _null_ jsonb_object_agg_finalfn _null_ _null_ _null_ )
+insert ( 3270 jsonb_object_agg 11 10 12 1 0 0 0 a f f f f i s 2 0 3802 "2276 2276" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3271 jsonb_build_array 11 10 12 1 0 2276 0 f f f f f s s 1 0 3802 2276 "{2276}" "{v}" _null_ _null_ _null_ jsonb_build_array _null_ _null_ _null_ )
+insert ( 3272 jsonb_build_array 11 10 12 1 0 0 0 f f f f f s s 0 0 3802 "" _null_ _null_ _null_ _null_ _null_ jsonb_build_array_noargs _null_ _null_ _null_ )
+insert ( 3273 jsonb_build_object 11 10 12 1 0 2276 0 f f f f f s s 1 0 3802 2276 "{2276}" "{v}" _null_ _null_ _null_ jsonb_build_object _null_ _null_ _null_ )
+insert ( 3274 jsonb_build_object 11 10 12 1 0 0 0 f f f f f s s 0 0 3802 "" _null_ _null_ _null_ _null_ _null_ jsonb_build_object_noargs _null_ _null_ _null_ )
+insert ( 3262 jsonb_strip_nulls 11 10 12 1 0 0 0 f f f t f i s 1 0 3802 3802 _null_ _null_ _null_ _null_ _null_ jsonb_strip_nulls _null_ _null_ _null_ )
+insert ( 3478 jsonb_object_field 11 10 12 1 0 0 0 f f f t f i s 2 0 3802 "3802 25" _null_ _null_ "{from_json, field_name}" _null_ _null_ jsonb_object_field _null_ _null_ _null_ )
+insert ( 3214 jsonb_object_field_text 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "3802 25" _null_ _null_ "{from_json, field_name}" _null_ _null_ jsonb_object_field_text _null_ _null_ _null_ )
+insert ( 3215 jsonb_array_element 11 10 12 1 0 0 0 f f f t f i s 2 0 3802 "3802 23" _null_ _null_ "{from_json, element_index}" _null_ _null_ jsonb_array_element _null_ _null_ _null_ )
+insert ( 3216 jsonb_array_element_text 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "3802 23" _null_ _null_ "{from_json, element_index}" _null_ _null_ jsonb_array_element_text _null_ _null_ _null_ )
+insert ( 3217 jsonb_extract_path 11 10 12 1 0 25 0 f f f t f i s 2 0 3802 "3802 1009" "{3802,1009}" "{i,v}" "{from_json,path_elems}" _null_ _null_ jsonb_extract_path _null_ _null_ _null_ )
+insert ( 3940 jsonb_extract_path_text 11 10 12 1 0 25 0 f f f t f i s 2 0 25 "3802 1009" "{3802,1009}" "{i,v}" "{from_json,path_elems}" _null_ _null_ jsonb_extract_path_text _null_ _null_ _null_ )
+insert ( 3219 jsonb_array_elements 11 10 12 1 100 0 0 f f f t t i s 1 0 3802 3802 "{3802,3802}" "{i,o}" "{from_json,value}" _null_ _null_ jsonb_array_elements _null_ _null_ _null_ )
+insert ( 3465 jsonb_array_elements_text 11 10 12 1 100 0 0 f f f t t i s 1 0 25 3802 "{3802,25}" "{i,o}" "{from_json,value}" _null_ _null_ jsonb_array_elements_text _null_ _null_ _null_ )
+insert ( 3207 jsonb_array_length 11 10 12 1 0 0 0 f f f t f i s 1 0 23 3802 _null_ _null_ _null_ _null_ _null_ jsonb_array_length _null_ _null_ _null_ )
+insert ( 3931 jsonb_object_keys 11 10 12 1 100 0 0 f f f t t i s 1 0 25 3802 _null_ _null_ _null_ _null_ _null_ jsonb_object_keys _null_ _null_ _null_ )
+insert ( 3208 jsonb_each 11 10 12 1 100 0 0 f f f t t i s 1 0 2249 3802 "{3802,25,3802}" "{i,o,o}" "{from_json,key,value}" _null_ _null_ jsonb_each _null_ _null_ _null_ )
+insert ( 3932 jsonb_each_text 11 10 12 1 100 0 0 f f f t t i s 1 0 2249 3802 "{3802,25,25}" "{i,o,o}" "{from_json,key,value}" _null_ _null_ jsonb_each_text _null_ _null_ _null_ )
+insert ( 3209 jsonb_populate_record 11 10 12 1 0 0 0 f f f f f s s 2 0 2283 "2283 3802" _null_ _null_ _null_ _null_ _null_ jsonb_populate_record _null_ _null_ _null_ )
+insert ( 3475 jsonb_populate_recordset 11 10 12 1 100 0 0 f f f f t s s 2 0 2283 "2283 3802" _null_ _null_ _null_ _null_ _null_ jsonb_populate_recordset _null_ _null_ _null_ )
+insert ( 3490 jsonb_to_record 11 10 12 1 0 0 0 f f f t f s s 1 0 2249 3802 _null_ _null_ _null_ _null_ _null_ jsonb_to_record _null_ _null_ _null_ )
+insert ( 3491 jsonb_to_recordset 11 10 12 1 100 0 0 f f f f t s s 1 0 2249 3802 _null_ _null_ _null_ _null_ _null_ jsonb_to_recordset _null_ _null_ _null_ )
+insert ( 3210 jsonb_typeof 11 10 12 1 0 0 0 f f f t f i s 1 0 25 3802 _null_ _null_ _null_ _null_ _null_ jsonb_typeof _null_ _null_ _null_ )
+insert ( 4038 jsonb_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_ne _null_ _null_ _null_ )
+insert ( 4039 jsonb_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_lt _null_ _null_ _null_ )
+insert ( 4040 jsonb_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_gt _null_ _null_ _null_ )
+insert ( 4041 jsonb_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_le _null_ _null_ _null_ )
+insert ( 4042 jsonb_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_ge _null_ _null_ _null_ )
+insert ( 4043 jsonb_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_eq _null_ _null_ _null_ )
+insert ( 4044 jsonb_cmp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_cmp _null_ _null_ _null_ )
+insert ( 4045 jsonb_hash 11 10 12 1 0 0 0 f f f t f i s 1 0 23 3802 _null_ _null_ _null_ _null_ _null_ jsonb_hash _null_ _null_ _null_ )
+insert ( 3416 jsonb_hash_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "3802 20" _null_ _null_ _null_ _null_ _null_ jsonb_hash_extended _null_ _null_ _null_ )
+insert ( 4046 jsonb_contains 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_contains _null_ _null_ _null_ )
+insert ( 4047 jsonb_exists 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 25" _null_ _null_ _null_ _null_ _null_ jsonb_exists _null_ _null_ _null_ )
+insert ( 4048 jsonb_exists_any 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 1009" _null_ _null_ _null_ _null_ _null_ jsonb_exists_any _null_ _null_ _null_ )
+insert ( 4049 jsonb_exists_all 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 1009" _null_ _null_ _null_ _null_ _null_ jsonb_exists_all _null_ _null_ _null_ )
+insert ( 4050 jsonb_contained 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_contained _null_ _null_ _null_ )
+insert ( 3480 gin_compare_jsonb 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "25 25" _null_ _null_ _null_ _null_ _null_ gin_compare_jsonb _null_ _null_ _null_ )
+insert ( 3482 gin_extract_jsonb 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "3802 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_extract_jsonb _null_ _null_ _null_ )
+insert ( 3483 gin_extract_jsonb_query 11 10 12 1 0 0 0 f f f t f i s 7 0 2281 "3802 2281 21 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_extract_jsonb_query _null_ _null_ _null_ )
+insert ( 3484 gin_consistent_jsonb 11 10 12 1 0 0 0 f f f t f i s 8 0 16 "2281 21 3802 23 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_consistent_jsonb _null_ _null_ _null_ )
+insert ( 3488 gin_triconsistent_jsonb 11 10 12 1 0 0 0 f f f t f i s 7 0 18 "2281 21 3802 23 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_triconsistent_jsonb _null_ _null_ _null_ )
+insert ( 3485 gin_extract_jsonb_path 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "3802 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_extract_jsonb_path _null_ _null_ _null_ )
+insert ( 3486 gin_extract_jsonb_query_path 11 10 12 1 0 0 0 f f f t f i s 7 0 2281 "3802 2281 21 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_extract_jsonb_query_path _null_ _null_ _null_ )
+insert ( 3487 gin_consistent_jsonb_path 11 10 12 1 0 0 0 f f f t f i s 8 0 16 "2281 21 3802 23 2281 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_consistent_jsonb_path _null_ _null_ _null_ )
+insert ( 3489 gin_triconsistent_jsonb_path 11 10 12 1 0 0 0 f f f t f i s 7 0 18 "2281 21 3802 23 2281 2281 2281" _null_ _null_ _null_ _null_ _null_ gin_triconsistent_jsonb_path _null_ _null_ _null_ )
+insert ( 3301 jsonb_concat 11 10 12 1 0 0 0 f f f t f i s 2 0 3802 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_concat _null_ _null_ _null_ )
+insert ( 3302 jsonb_delete 11 10 12 1 0 0 0 f f f t f i s 2 0 3802 "3802 25" _null_ _null_ _null_ _null_ _null_ jsonb_delete _null_ _null_ _null_ )
+insert ( 3303 jsonb_delete 11 10 12 1 0 0 0 f f f t f i s 2 0 3802 "3802 23" _null_ _null_ _null_ _null_ _null_ jsonb_delete_idx _null_ _null_ _null_ )
+insert ( 3343 jsonb_delete 11 10 12 1 0 25 0 f f f t f i s 2 0 3802 "3802 1009" "{3802,1009}" "{i,v}" "{from_json,path_elems}" _null_ _null_ jsonb_delete_array _null_ _null_ _null_ )
+insert ( 3304 jsonb_delete_path 11 10 12 1 0 0 0 f f f t f i s 2 0 3802 "3802 1009" _null_ _null_ _null_ _null_ _null_ jsonb_delete_path _null_ _null_ _null_ )
+insert ( 5054 jsonb_set_lax 11 10 12 1 0 0 0 f f f f f i s 5 0 3802 "3802 1009 3802 16 25" _null_ _null_ _null_ _null_ _null_ jsonb_set_lax _null_ _null_ _null_ )
+insert ( 3305 jsonb_set 11 10 12 1 0 0 0 f f f t f i s 4 0 3802 "3802 1009 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_set _null_ _null_ _null_ )
+insert ( 3306 jsonb_pretty 11 10 12 1 0 0 0 f f f t f i s 1 0 25 3802 _null_ _null_ _null_ _null_ _null_ jsonb_pretty _null_ _null_ _null_ )
+insert ( 3579 jsonb_insert 11 10 12 1 0 0 0 f f f t f i s 4 0 3802 "3802 1009 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_insert _null_ _null_ _null_ )
+insert ( 4001 jsonpath_in 11 10 12 1 0 0 0 f f f t f i s 1 0 4072 2275 _null_ _null_ _null_ _null_ _null_ jsonpath_in _null_ _null_ _null_ )
+insert ( 4002 jsonpath_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 4072 2281 _null_ _null_ _null_ _null_ _null_ jsonpath_recv _null_ _null_ _null_ )
+insert ( 4003 jsonpath_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 4072 _null_ _null_ _null_ _null_ _null_ jsonpath_out _null_ _null_ _null_ )
+insert ( 4004 jsonpath_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 4072 _null_ _null_ _null_ _null_ _null_ jsonpath_send _null_ _null_ _null_ )
+insert ( 4005 jsonb_path_exists 11 10 12 1 0 0 0 f f f t f i s 4 0 16 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_exists _null_ _null_ _null_ )
+insert ( 4006 jsonb_path_query 11 10 12 1 1000 0 0 f f f t t i s 4 0 3802 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_query _null_ _null_ _null_ )
+insert ( 4007 jsonb_path_query_array 11 10 12 1 0 0 0 f f f t f i s 4 0 3802 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_query_array _null_ _null_ _null_ )
+insert ( 4008 jsonb_path_query_first 11 10 12 1 0 0 0 f f f t f i s 4 0 3802 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_query_first _null_ _null_ _null_ )
+insert ( 4009 jsonb_path_match 11 10 12 1 0 0 0 f f f t f i s 4 0 16 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_match _null_ _null_ _null_ )
+insert ( 1177 jsonb_path_exists_tz 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_exists_tz _null_ _null_ _null_ )
+insert ( 1179 jsonb_path_query_tz 11 10 12 1 1000 0 0 f f f t t s s 4 0 3802 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_query_tz _null_ _null_ _null_ )
+insert ( 1180 jsonb_path_query_array_tz 11 10 12 1 0 0 0 f f f t f s s 4 0 3802 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_query_array_tz _null_ _null_ _null_ )
+insert ( 2023 jsonb_path_query_first_tz 11 10 12 1 0 0 0 f f f t f s s 4 0 3802 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_query_first_tz _null_ _null_ _null_ )
+insert ( 2030 jsonb_path_match_tz 11 10 12 1 0 0 0 f f f t f s s 4 0 16 "3802 4072 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_path_match_tz _null_ _null_ _null_ )
+insert ( 4010 jsonb_path_exists_opr 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 4072" _null_ _null_ _null_ _null_ _null_ jsonb_path_exists_opr _null_ _null_ _null_ )
+insert ( 4011 jsonb_path_match_opr 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3802 4072" _null_ _null_ _null_ _null_ _null_ jsonb_path_match_opr _null_ _null_ _null_ )
+insert ( 2939 txid_snapshot_in 11 10 12 1 0 0 0 f f f t f i s 1 0 2970 2275 _null_ _null_ _null_ _null_ _null_ pg_snapshot_in _null_ _null_ _null_ )
+insert ( 2940 txid_snapshot_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 2970 _null_ _null_ _null_ _null_ _null_ pg_snapshot_out _null_ _null_ _null_ )
+insert ( 2941 txid_snapshot_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 2970 2281 _null_ _null_ _null_ _null_ _null_ pg_snapshot_recv _null_ _null_ _null_ )
+insert ( 2942 txid_snapshot_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 2970 _null_ _null_ _null_ _null_ _null_ pg_snapshot_send _null_ _null_ _null_ )
+insert ( 2943 txid_current 11 10 12 1 0 0 0 f f f t f s u 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_current_xact_id _null_ _null_ _null_ )
+insert ( 3348 txid_current_if_assigned 11 10 12 1 0 0 0 f f f t f s u 0 0 20 "" _null_ _null_ _null_ _null_ _null_ pg_current_xact_id_if_assigned _null_ _null_ _null_ )
+insert ( 2944 txid_current_snapshot 11 10 12 1 0 0 0 f f f t f s s 0 0 2970 "" _null_ _null_ _null_ _null_ _null_ pg_current_snapshot _null_ _null_ _null_ )
+insert ( 2945 txid_snapshot_xmin 11 10 12 1 0 0 0 f f f t f i s 1 0 20 2970 _null_ _null_ _null_ _null_ _null_ pg_snapshot_xmin _null_ _null_ _null_ )
+insert ( 2946 txid_snapshot_xmax 11 10 12 1 0 0 0 f f f t f i s 1 0 20 2970 _null_ _null_ _null_ _null_ _null_ pg_snapshot_xmax _null_ _null_ _null_ )
+insert ( 2947 txid_snapshot_xip 11 10 12 1 50 0 0 f f f t t i s 1 0 20 2970 _null_ _null_ _null_ _null_ _null_ pg_snapshot_xip _null_ _null_ _null_ )
+insert ( 2948 txid_visible_in_snapshot 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "20 2970" _null_ _null_ _null_ _null_ _null_ pg_visible_in_snapshot _null_ _null_ _null_ )
+insert ( 3360 txid_status 11 10 12 1 0 0 0 f f f t f v s 1 0 25 20 _null_ _null_ _null_ _null_ _null_ pg_xact_status _null_ _null_ _null_ )
+insert ( 5055 pg_snapshot_in 11 10 12 1 0 0 0 f f f t f i s 1 0 5038 2275 _null_ _null_ _null_ _null_ _null_ pg_snapshot_in _null_ _null_ _null_ )
+insert ( 5056 pg_snapshot_out 11 10 12 1 0 0 0 f f f t f i s 1 0 2275 5038 _null_ _null_ _null_ _null_ _null_ pg_snapshot_out _null_ _null_ _null_ )
+insert ( 5057 pg_snapshot_recv 11 10 12 1 0 0 0 f f f t f i s 1 0 5038 2281 _null_ _null_ _null_ _null_ _null_ pg_snapshot_recv _null_ _null_ _null_ )
+insert ( 5058 pg_snapshot_send 11 10 12 1 0 0 0 f f f t f i s 1 0 17 5038 _null_ _null_ _null_ _null_ _null_ pg_snapshot_send _null_ _null_ _null_ )
+insert ( 5061 pg_current_snapshot 11 10 12 1 0 0 0 f f f t f s s 0 0 5038 "" _null_ _null_ _null_ _null_ _null_ pg_current_snapshot _null_ _null_ _null_ )
+insert ( 5062 pg_snapshot_xmin 11 10 12 1 0 0 0 f f f t f i s 1 0 5069 5038 _null_ _null_ _null_ _null_ _null_ pg_snapshot_xmin _null_ _null_ _null_ )
+insert ( 5063 pg_snapshot_xmax 11 10 12 1 0 0 0 f f f t f i s 1 0 5069 5038 _null_ _null_ _null_ _null_ _null_ pg_snapshot_xmax _null_ _null_ _null_ )
+insert ( 5064 pg_snapshot_xip 11 10 12 1 50 0 0 f f f t t i s 1 0 5069 5038 _null_ _null_ _null_ _null_ _null_ pg_snapshot_xip _null_ _null_ _null_ )
+insert ( 5065 pg_visible_in_snapshot 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "5069 5038" _null_ _null_ _null_ _null_ _null_ pg_visible_in_snapshot _null_ _null_ _null_ )
+insert ( 5059 pg_current_xact_id 11 10 12 1 0 0 0 f f f t f s u 0 0 5069 "" _null_ _null_ _null_ _null_ _null_ pg_current_xact_id _null_ _null_ _null_ )
+insert ( 5060 pg_current_xact_id_if_assigned 11 10 12 1 0 0 0 f f f t f s u 0 0 5069 "" _null_ _null_ _null_ _null_ _null_ pg_current_xact_id_if_assigned _null_ _null_ _null_ )
+insert ( 5066 pg_xact_status 11 10 12 1 0 0 0 f f f t f v s 1 0 25 5069 _null_ _null_ _null_ _null_ _null_ pg_xact_status _null_ _null_ _null_ )
+insert ( 2981 record_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_eq _null_ _null_ _null_ )
+insert ( 2982 record_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_ne _null_ _null_ _null_ )
+insert ( 2983 record_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_lt _null_ _null_ _null_ )
+insert ( 2984 record_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_gt _null_ _null_ _null_ )
+insert ( 2985 record_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_le _null_ _null_ _null_ )
+insert ( 2986 record_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_ge _null_ _null_ _null_ )
+insert ( 2987 btrecordcmp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "2249 2249" _null_ _null_ _null_ _null_ _null_ btrecordcmp _null_ _null_ _null_ )
+insert ( 3181 record_image_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_image_eq _null_ _null_ _null_ )
+insert ( 3182 record_image_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_image_ne _null_ _null_ _null_ )
+insert ( 3183 record_image_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_image_lt _null_ _null_ _null_ )
+insert ( 3184 record_image_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_image_gt _null_ _null_ _null_ )
+insert ( 3185 record_image_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_image_le _null_ _null_ _null_ )
+insert ( 3186 record_image_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2249 2249" _null_ _null_ _null_ _null_ _null_ record_image_ge _null_ _null_ _null_ )
+insert ( 3187 btrecordimagecmp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "2249 2249" _null_ _null_ _null_ _null_ _null_ btrecordimagecmp _null_ _null_ _null_ )
+insert ( 5051 btequalimage 11 10 12 1 0 0 0 f f f t f i s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ btequalimage _null_ _null_ _null_ )
+insert ( 3082 pg_available_extensions 11 10 12 10 100 0 0 f f f t t s s 0 0 2249 "" "{19,25,25}" "{o,o,o}" "{name,default_version,comment}" _null_ _null_ pg_available_extensions _null_ _null_ _null_ )
+insert ( 3083 pg_available_extension_versions 11 10 12 10 100 0 0 f f f t t s s 0 0 2249 "" "{19,25,16,16,16,19,1003,25}" "{o,o,o,o,o,o,o,o}" "{name,version,superuser,trusted,relocatable,schema,requires,comment}" _null_ _null_ pg_available_extension_versions _null_ _null_ _null_ )
+insert ( 3084 pg_extension_update_paths 11 10 12 10 100 0 0 f f f t t s s 1 0 2249 19 "{19,25,25,25}" "{i,o,o,o}" "{name,source,target,path}" _null_ _null_ pg_extension_update_paths _null_ _null_ _null_ )
+insert ( 3086 pg_extension_config_dump 11 10 12 1 0 0 0 f f f t f v u 2 0 2278 "2205 25" _null_ _null_ _null_ _null_ _null_ pg_extension_config_dump _null_ _null_ _null_ )
+insert ( 3100 row_number 11 10 12 1 0 0 0 w f f f f i s 0 0 20 "" _null_ _null_ _null_ _null_ _null_ window_row_number _null_ _null_ _null_ )
+insert ( 3101 rank 11 10 12 1 0 0 0 w f f f f i s 0 0 20 "" _null_ _null_ _null_ _null_ _null_ window_rank _null_ _null_ _null_ )
+insert ( 3102 dense_rank 11 10 12 1 0 0 0 w f f f f i s 0 0 20 "" _null_ _null_ _null_ _null_ _null_ window_dense_rank _null_ _null_ _null_ )
+insert ( 3103 percent_rank 11 10 12 1 0 0 0 w f f f f i s 0 0 701 "" _null_ _null_ _null_ _null_ _null_ window_percent_rank _null_ _null_ _null_ )
+insert ( 3104 cume_dist 11 10 12 1 0 0 0 w f f f f i s 0 0 701 "" _null_ _null_ _null_ _null_ _null_ window_cume_dist _null_ _null_ _null_ )
+insert ( 3105 ntile 11 10 12 1 0 0 0 w f f t f i s 1 0 23 23 _null_ _null_ _null_ _null_ _null_ window_ntile _null_ _null_ _null_ )
+insert ( 3106 lag 11 10 12 1 0 0 0 w f f t f i s 1 0 2283 2283 _null_ _null_ _null_ _null_ _null_ window_lag _null_ _null_ _null_ )
+insert ( 3107 lag 11 10 12 1 0 0 0 w f f t f i s 2 0 2283 "2283 23" _null_ _null_ _null_ _null_ _null_ window_lag_with_offset _null_ _null_ _null_ )
+insert ( 3108 lag 11 10 12 1 0 0 0 w f f t f i s 3 0 2283 "2283 23 2283" _null_ _null_ _null_ _null_ _null_ window_lag_with_offset_and_default _null_ _null_ _null_ )
+insert ( 3109 lead 11 10 12 1 0 0 0 w f f t f i s 1 0 2283 2283 _null_ _null_ _null_ _null_ _null_ window_lead _null_ _null_ _null_ )
+insert ( 3110 lead 11 10 12 1 0 0 0 w f f t f i s 2 0 2283 "2283 23" _null_ _null_ _null_ _null_ _null_ window_lead_with_offset _null_ _null_ _null_ )
+insert ( 3111 lead 11 10 12 1 0 0 0 w f f t f i s 3 0 2283 "2283 23 2283" _null_ _null_ _null_ _null_ _null_ window_lead_with_offset_and_default _null_ _null_ _null_ )
+insert ( 3112 first_value 11 10 12 1 0 0 0 w f f t f i s 1 0 2283 2283 _null_ _null_ _null_ _null_ _null_ window_first_value _null_ _null_ _null_ )
+insert ( 3113 last_value 11 10 12 1 0 0 0 w f f t f i s 1 0 2283 2283 _null_ _null_ _null_ _null_ _null_ window_last_value _null_ _null_ _null_ )
+insert ( 3114 nth_value 11 10 12 1 0 0 0 w f f t f i s 2 0 2283 "2283 23" _null_ _null_ _null_ _null_ _null_ window_nth_value _null_ _null_ _null_ )
+insert ( 3832 anyrange_in 11 10 12 1 0 0 0 f f f t f s s 3 0 3831 "2275 26 23" _null_ _null_ _null_ _null_ _null_ anyrange_in _null_ _null_ _null_ )
+insert ( 3833 anyrange_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 3831 _null_ _null_ _null_ _null_ _null_ anyrange_out _null_ _null_ _null_ )
+insert ( 3834 range_in 11 10 12 1 0 0 0 f f f t f s s 3 0 3831 "2275 26 23" _null_ _null_ _null_ _null_ _null_ range_in _null_ _null_ _null_ )
+insert ( 3835 range_out 11 10 12 1 0 0 0 f f f t f s s 1 0 2275 3831 _null_ _null_ _null_ _null_ _null_ range_out _null_ _null_ _null_ )
+insert ( 3836 range_recv 11 10 12 1 0 0 0 f f f t f s s 3 0 3831 "2281 26 23" _null_ _null_ _null_ _null_ _null_ range_recv _null_ _null_ _null_ )
+insert ( 3837 range_send 11 10 12 1 0 0 0 f f f t f s s 1 0 17 3831 _null_ _null_ _null_ _null_ _null_ range_send _null_ _null_ _null_ )
+insert ( 3848 lower 11 10 12 1 0 0 0 f f f t f i s 1 0 2283 3831 _null_ _null_ _null_ _null_ _null_ range_lower _null_ _null_ _null_ )
+insert ( 3849 upper 11 10 12 1 0 0 0 f f f t f i s 1 0 2283 3831 _null_ _null_ _null_ _null_ _null_ range_upper _null_ _null_ _null_ )
+insert ( 3850 isempty 11 10 12 1 0 0 0 f f f t f i s 1 0 16 3831 _null_ _null_ _null_ _null_ _null_ range_empty _null_ _null_ _null_ )
+insert ( 3851 lower_inc 11 10 12 1 0 0 0 f f f t f i s 1 0 16 3831 _null_ _null_ _null_ _null_ _null_ range_lower_inc _null_ _null_ _null_ )
+insert ( 3852 upper_inc 11 10 12 1 0 0 0 f f f t f i s 1 0 16 3831 _null_ _null_ _null_ _null_ _null_ range_upper_inc _null_ _null_ _null_ )
+insert ( 3853 lower_inf 11 10 12 1 0 0 0 f f f t f i s 1 0 16 3831 _null_ _null_ _null_ _null_ _null_ range_lower_inf _null_ _null_ _null_ )
+insert ( 3854 upper_inf 11 10 12 1 0 0 0 f f f t f i s 1 0 16 3831 _null_ _null_ _null_ _null_ _null_ range_upper_inf _null_ _null_ _null_ )
+insert ( 3855 range_eq 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_eq _null_ _null_ _null_ )
+insert ( 3856 range_ne 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_ne _null_ _null_ _null_ )
+insert ( 3857 range_overlaps 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_overlaps _null_ _null_ _null_ )
+insert ( 3858 range_contains_elem 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 2283" _null_ _null_ _null_ _null_ _null_ range_contains_elem _null_ _null_ _null_ )
+insert ( 3859 range_contains 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_contains _null_ _null_ _null_ )
+insert ( 3860 elem_contained_by_range 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2283 3831" _null_ _null_ _null_ _null_ _null_ elem_contained_by_range _null_ _null_ _null_ )
+insert ( 3861 range_contained_by 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_contained_by _null_ _null_ _null_ )
+insert ( 3862 range_adjacent 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_adjacent _null_ _null_ _null_ )
+insert ( 3863 range_before 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_before _null_ _null_ _null_ )
+insert ( 3864 range_after 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_after _null_ _null_ _null_ )
+insert ( 3865 range_overleft 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_overleft _null_ _null_ _null_ )
+insert ( 3866 range_overright 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_overright _null_ _null_ _null_ )
+insert ( 3867 range_union 11 10 12 1 0 0 0 f f f t f i s 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_union _null_ _null_ _null_ )
+insert ( 4057 range_merge 11 10 12 1 0 0 0 f f f t f i s 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_merge _null_ _null_ _null_ )
+insert ( 3868 range_intersect 11 10 12 1 0 0 0 f f f t f i s 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_intersect _null_ _null_ _null_ )
+insert ( 3869 range_minus 11 10 12 1 0 0 0 f f f t f i s 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_minus _null_ _null_ _null_ )
+insert ( 3870 range_cmp 11 10 12 1 0 0 0 f f f t f i s 2 0 23 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_cmp _null_ _null_ _null_ )
+insert ( 3871 range_lt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_lt _null_ _null_ _null_ )
+insert ( 3872 range_le 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_le _null_ _null_ _null_ )
+insert ( 3873 range_ge 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_ge _null_ _null_ _null_ )
+insert ( 3874 range_gt 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_gt _null_ _null_ _null_ )
+insert ( 3875 range_gist_consistent 11 10 12 1 0 0 0 f f f t f i s 5 0 16 "2281 3831 21 26 2281" _null_ _null_ _null_ _null_ _null_ range_gist_consistent _null_ _null_ _null_ )
+insert ( 3876 range_gist_union 11 10 12 1 0 0 0 f f f t f i s 2 0 3831 "2281 2281" _null_ _null_ _null_ _null_ _null_ range_gist_union _null_ _null_ _null_ )
+insert ( 3879 range_gist_penalty 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ _null_ range_gist_penalty _null_ _null_ _null_ )
+insert ( 3880 range_gist_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ _null_ range_gist_picksplit _null_ _null_ _null_ )
+insert ( 3881 range_gist_same 11 10 12 1 0 0 0 f f f t f i s 3 0 2281 "3831 3831 2281" _null_ _null_ _null_ _null_ _null_ range_gist_same _null_ _null_ _null_ )
+insert ( 3902 hash_range 11 10 12 1 0 0 0 f f f t f i s 1 0 23 3831 _null_ _null_ _null_ _null_ _null_ hash_range _null_ _null_ _null_ )
+insert ( 3417 hash_range_extended 11 10 12 1 0 0 0 f f f t f i s 2 0 20 "3831 20" _null_ _null_ _null_ _null_ _null_ hash_range_extended _null_ _null_ _null_ )
+insert ( 3916 range_typanalyze 11 10 12 1 0 0 0 f f f t f s s 1 0 16 2281 _null_ _null_ _null_ _null_ _null_ range_typanalyze _null_ _null_ _null_ )
+insert ( 3169 rangesel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ rangesel _null_ _null_ _null_ )
+insert ( 3914 int4range_canonical 11 10 12 1 0 0 0 f f f t f i s 1 0 3904 3904 _null_ _null_ _null_ _null_ _null_ int4range_canonical _null_ _null_ _null_ )
+insert ( 3928 int8range_canonical 11 10 12 1 0 0 0 f f f t f i s 1 0 3926 3926 _null_ _null_ _null_ _null_ _null_ int8range_canonical _null_ _null_ _null_ )
+insert ( 3915 daterange_canonical 11 10 12 1 0 0 0 f f f t f i s 1 0 3912 3912 _null_ _null_ _null_ _null_ _null_ daterange_canonical _null_ _null_ _null_ )
+insert ( 3922 int4range_subdiff 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "23 23" _null_ _null_ _null_ _null_ _null_ int4range_subdiff _null_ _null_ _null_ )
+insert ( 3923 int8range_subdiff 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "20 20" _null_ _null_ _null_ _null_ _null_ int8range_subdiff _null_ _null_ _null_ )
+insert ( 3924 numrange_subdiff 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "1700 1700" _null_ _null_ _null_ _null_ _null_ numrange_subdiff _null_ _null_ _null_ )
+insert ( 3925 daterange_subdiff 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "1082 1082" _null_ _null_ _null_ _null_ _null_ daterange_subdiff _null_ _null_ _null_ )
+insert ( 3929 tsrange_subdiff 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "1114 1114" _null_ _null_ _null_ _null_ _null_ tsrange_subdiff _null_ _null_ _null_ )
+insert ( 3930 tstzrange_subdiff 11 10 12 1 0 0 0 f f f t f i s 2 0 701 "1184 1184" _null_ _null_ _null_ _null_ _null_ tstzrange_subdiff _null_ _null_ _null_ )
+insert ( 3840 int4range 11 10 12 1 0 0 0 f f f f f i s 2 0 3904 "23 23" _null_ _null_ _null_ _null_ _null_ range_constructor2 _null_ _null_ _null_ )
+insert ( 3841 int4range 11 10 12 1 0 0 0 f f f f f i s 3 0 3904 "23 23 25" _null_ _null_ _null_ _null_ _null_ range_constructor3 _null_ _null_ _null_ )
+insert ( 3844 numrange 11 10 12 1 0 0 0 f f f f f i s 2 0 3906 "1700 1700" _null_ _null_ _null_ _null_ _null_ range_constructor2 _null_ _null_ _null_ )
+insert ( 3845 numrange 11 10 12 1 0 0 0 f f f f f i s 3 0 3906 "1700 1700 25" _null_ _null_ _null_ _null_ _null_ range_constructor3 _null_ _null_ _null_ )
+insert ( 3933 tsrange 11 10 12 1 0 0 0 f f f f f i s 2 0 3908 "1114 1114" _null_ _null_ _null_ _null_ _null_ range_constructor2 _null_ _null_ _null_ )
+insert ( 3934 tsrange 11 10 12 1 0 0 0 f f f f f i s 3 0 3908 "1114 1114 25" _null_ _null_ _null_ _null_ _null_ range_constructor3 _null_ _null_ _null_ )
+insert ( 3937 tstzrange 11 10 12 1 0 0 0 f f f f f i s 2 0 3910 "1184 1184" _null_ _null_ _null_ _null_ _null_ range_constructor2 _null_ _null_ _null_ )
+insert ( 3938 tstzrange 11 10 12 1 0 0 0 f f f f f i s 3 0 3910 "1184 1184 25" _null_ _null_ _null_ _null_ _null_ range_constructor3 _null_ _null_ _null_ )
+insert ( 3941 daterange 11 10 12 1 0 0 0 f f f f f i s 2 0 3912 "1082 1082" _null_ _null_ _null_ _null_ _null_ range_constructor2 _null_ _null_ _null_ )
+insert ( 3942 daterange 11 10 12 1 0 0 0 f f f f f i s 3 0 3912 "1082 1082 25" _null_ _null_ _null_ _null_ _null_ range_constructor3 _null_ _null_ _null_ )
+insert ( 3945 int8range 11 10 12 1 0 0 0 f f f f f i s 2 0 3926 "20 20" _null_ _null_ _null_ _null_ _null_ range_constructor2 _null_ _null_ _null_ )
+insert ( 3946 int8range 11 10 12 1 0 0 0 f f f f f i s 3 0 3926 "20 20 25" _null_ _null_ _null_ _null_ _null_ range_constructor3 _null_ _null_ _null_ )
+insert ( 3846 make_date 11 10 12 1 0 0 0 f f f t f i s 3 0 1082 "23 23 23" _null_ _null_ "{year,month,day}" _null_ _null_ make_date _null_ _null_ _null_ )
+insert ( 3847 make_time 11 10 12 1 0 0 0 f f f t f i s 3 0 1083 "23 23 701" _null_ _null_ "{hour,min,sec}" _null_ _null_ make_time _null_ _null_ _null_ )
+insert ( 3461 make_timestamp 11 10 12 1 0 0 0 f f f t f i s 6 0 1114 "23 23 23 23 23 701" _null_ _null_ "{year,month,mday,hour,min,sec}" _null_ _null_ make_timestamp _null_ _null_ _null_ )
+insert ( 3462 make_timestamptz 11 10 12 1 0 0 0 f f f t f s s 6 0 1184 "23 23 23 23 23 701" _null_ _null_ "{year,month,mday,hour,min,sec}" _null_ _null_ make_timestamptz _null_ _null_ _null_ )
+insert ( 3463 make_timestamptz 11 10 12 1 0 0 0 f f f t f s s 7 0 1184 "23 23 23 23 23 701 25" _null_ _null_ "{year,month,mday,hour,min,sec,timezone}" _null_ _null_ make_timestamptz_at_timezone _null_ _null_ _null_ )
+insert ( 3464 make_interval 11 10 12 1 0 0 0 f f f t f i s 7 0 1186 "23 23 23 23 23 23 701" _null_ _null_ "{years,months,weeks,days,hours,mins,secs}" _null_ _null_ make_interval _null_ _null_ _null_ )
+insert ( 4018 spg_quad_config 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_quad_config _null_ _null_ _null_ )
+insert ( 4019 spg_quad_choose 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_quad_choose _null_ _null_ _null_ )
+insert ( 4020 spg_quad_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_quad_picksplit _null_ _null_ _null_ )
+insert ( 4021 spg_quad_inner_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_quad_inner_consistent _null_ _null_ _null_ )
+insert ( 4022 spg_quad_leaf_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_quad_leaf_consistent _null_ _null_ _null_ )
+insert ( 4023 spg_kd_config 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_kd_config _null_ _null_ _null_ )
+insert ( 4024 spg_kd_choose 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_kd_choose _null_ _null_ _null_ )
+insert ( 4025 spg_kd_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_kd_picksplit _null_ _null_ _null_ )
+insert ( 4026 spg_kd_inner_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_kd_inner_consistent _null_ _null_ _null_ )
+insert ( 4027 spg_text_config 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_text_config _null_ _null_ _null_ )
+insert ( 4028 spg_text_choose 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_text_choose _null_ _null_ _null_ )
+insert ( 4029 spg_text_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_text_picksplit _null_ _null_ _null_ )
+insert ( 4030 spg_text_inner_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_text_inner_consistent _null_ _null_ _null_ )
+insert ( 4031 spg_text_leaf_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_text_leaf_consistent _null_ _null_ _null_ )
+insert ( 3469 spg_range_quad_config 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_range_quad_config _null_ _null_ _null_ )
+insert ( 3470 spg_range_quad_choose 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_range_quad_choose _null_ _null_ _null_ )
+insert ( 3471 spg_range_quad_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_range_quad_picksplit _null_ _null_ _null_ )
+insert ( 3472 spg_range_quad_inner_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_range_quad_inner_consistent _null_ _null_ _null_ )
+insert ( 3473 spg_range_quad_leaf_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_range_quad_leaf_consistent _null_ _null_ _null_ )
+insert ( 5012 spg_box_quad_config 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_box_quad_config _null_ _null_ _null_ )
+insert ( 5013 spg_box_quad_choose 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_box_quad_choose _null_ _null_ _null_ )
+insert ( 5014 spg_box_quad_picksplit 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_box_quad_picksplit _null_ _null_ _null_ )
+insert ( 5015 spg_box_quad_inner_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_box_quad_inner_consistent _null_ _null_ _null_ )
+insert ( 5016 spg_box_quad_leaf_consistent 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_box_quad_leaf_consistent _null_ _null_ _null_ )
+insert ( 5010 spg_bbox_quad_config 11 10 12 1 0 0 0 f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_bbox_quad_config _null_ _null_ _null_ )
+insert ( 5011 spg_poly_quad_compress 11 10 12 1 0 0 0 f f f t f i s 1 0 603 604 _null_ _null_ _null_ _null_ _null_ spg_poly_quad_compress _null_ _null_ _null_ )
+insert ( 3779 pg_create_physical_replication_slot 11 10 12 1 0 0 0 f f f t f v u 3 0 2249 "19 16 16" "{19,16,16,19,3220}" "{i,i,i,o,o}" "{slot_name,immediately_reserve,temporary,slot_name,lsn}" _null_ _null_ pg_create_physical_replication_slot _null_ _null_ _null_ )
+insert ( 4220 pg_copy_physical_replication_slot 11 10 12 1 0 0 0 f f f t f v u 3 0 2249 "19 19 16" "{19,19,16,19,3220}" "{i,i,i,o,o}" "{src_slot_name,dst_slot_name,temporary,slot_name,lsn}" _null_ _null_ pg_copy_physical_replication_slot_a _null_ _null_ _null_ )
+insert ( 4221 pg_copy_physical_replication_slot 11 10 12 1 0 0 0 f f f t f v u 2 0 2249 "19 19" "{19,19,19,3220}" "{i,i,o,o}" "{src_slot_name,dst_slot_name,slot_name,lsn}" _null_ _null_ pg_copy_physical_replication_slot_b _null_ _null_ _null_ )
+insert ( 3780 pg_drop_replication_slot 11 10 12 1 0 0 0 f f f t f v u 1 0 2278 19 _null_ _null_ _null_ _null_ _null_ pg_drop_replication_slot _null_ _null_ _null_ )
+insert ( 3781 pg_get_replication_slots 11 10 12 1 10 0 0 f f f f t s s 0 0 2249 "" "{19,19,25,26,16,16,23,28,28,3220,3220,25,20}" "{o,o,o,o,o,o,o,o,o,o,o,o,o}" "{slot_name,plugin,slot_type,datoid,temporary,active,active_pid,xmin,catalog_xmin,restart_lsn,confirmed_flush_lsn,wal_status,safe_wal_size}" _null_ _null_ pg_get_replication_slots _null_ _null_ _null_ )
+insert ( 3786 pg_create_logical_replication_slot 11 10 12 1 0 0 0 f f f t f v u 3 0 2249 "19 19 16" "{19,19,16,19,3220}" "{i,i,i,o,o}" "{slot_name,plugin,temporary,slot_name,lsn}" _null_ _null_ pg_create_logical_replication_slot _null_ _null_ _null_ )
+insert ( 4222 pg_copy_logical_replication_slot 11 10 12 1 0 0 0 f f f t f v u 4 0 2249 "19 19 16 19" "{19,19,16,19,19,3220}" "{i,i,i,i,o,o}" "{src_slot_name,dst_slot_name,temporary,plugin,slot_name,lsn}" _null_ _null_ pg_copy_logical_replication_slot_a _null_ _null_ _null_ )
+insert ( 4223 pg_copy_logical_replication_slot 11 10 12 1 0 0 0 f f f t f v u 3 0 2249 "19 19 16" "{19,19,16,19,3220}" "{i,i,i,o,o}" "{src_slot_name,dst_slot_name,temporary,slot_name,lsn}" _null_ _null_ pg_copy_logical_replication_slot_b _null_ _null_ _null_ )
+insert ( 4224 pg_copy_logical_replication_slot 11 10 12 1 0 0 0 f f f t f v u 2 0 2249 "19 19" "{19,19,19,3220}" "{i,i,o,o}" "{src_slot_name,dst_slot_name,slot_name,lsn}" _null_ _null_ pg_copy_logical_replication_slot_c _null_ _null_ _null_ )
+insert ( 3782 pg_logical_slot_get_changes 11 10 12 1000 1000 25 0 f f f f t v u 4 0 2249 "19 3220 23 1009" "{19,3220,23,1009,3220,28,25}" "{i,i,i,v,o,o,o}" "{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}" _null_ _null_ pg_logical_slot_get_changes _null_ _null_ _null_ )
+insert ( 3783 pg_logical_slot_get_binary_changes 11 10 12 1000 1000 25 0 f f f f t v u 4 0 2249 "19 3220 23 1009" "{19,3220,23,1009,3220,28,17}" "{i,i,i,v,o,o,o}" "{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}" _null_ _null_ pg_logical_slot_get_binary_changes _null_ _null_ _null_ )
+insert ( 3784 pg_logical_slot_peek_changes 11 10 12 1000 1000 25 0 f f f f t v u 4 0 2249 "19 3220 23 1009" "{19,3220,23,1009,3220,28,25}" "{i,i,i,v,o,o,o}" "{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}" _null_ _null_ pg_logical_slot_peek_changes _null_ _null_ _null_ )
+insert ( 3785 pg_logical_slot_peek_binary_changes 11 10 12 1000 1000 25 0 f f f f t v u 4 0 2249 "19 3220 23 1009" "{19,3220,23,1009,3220,28,17}" "{i,i,i,v,o,o,o}" "{slot_name,upto_lsn,upto_nchanges,options,lsn,xid,data}" _null_ _null_ pg_logical_slot_peek_binary_changes _null_ _null_ _null_ )
+insert ( 3878 pg_replication_slot_advance 11 10 12 1 0 0 0 f f f t f v u 2 0 2249 "19 3220" "{19,3220,19,3220}" "{i,i,o,o}" "{slot_name,upto_lsn,slot_name,end_lsn}" _null_ _null_ pg_replication_slot_advance _null_ _null_ _null_ )
+insert ( 3577 pg_logical_emit_message 11 10 12 1 0 0 0 f f f t f v u 3 0 3220 "16 25 25" _null_ _null_ _null_ _null_ _null_ pg_logical_emit_message_text _null_ _null_ _null_ )
+insert ( 3578 pg_logical_emit_message 11 10 12 1 0 0 0 f f f t f v u 3 0 3220 "16 25 17" _null_ _null_ _null_ _null_ _null_ pg_logical_emit_message_bytea _null_ _null_ _null_ )
+insert ( 3566 pg_event_trigger_dropped_objects 11 10 12 10 100 0 0 f f f t t s r 0 0 2249 "" "{26,26,23,16,16,16,25,25,25,25,1009,1009}" "{o,o,o,o,o,o,o,o,o,o,o,o}" "{classid, objid, objsubid, original, normal, is_temporary, object_type, schema_name, object_name, object_identity, address_names, address_args}" _null_ _null_ pg_event_trigger_dropped_objects _null_ _null_ _null_ )
+insert ( 4566 pg_event_trigger_table_rewrite_oid 11 10 12 1 0 0 0 f f f t f s r 0 0 26 "" "{26}" "{o}" "{oid}" _null_ _null_ pg_event_trigger_table_rewrite_oid _null_ _null_ _null_ )
+insert ( 4567 pg_event_trigger_table_rewrite_reason 11 10 12 1 0 0 0 f f f t f s r 0 0 23 "" _null_ _null_ _null_ _null_ _null_ pg_event_trigger_table_rewrite_reason _null_ _null_ _null_ )
+insert ( 4568 pg_event_trigger_ddl_commands 11 10 12 10 100 0 0 f f f t t s r 0 0 2249 "" "{26,26,23,25,25,25,25,16,32}" "{o,o,o,o,o,o,o,o,o}" "{classid, objid, objsubid, command_tag, object_type, schema_name, object_identity, in_extension, command}" _null_ _null_ pg_event_trigger_ddl_commands _null_ _null_ _null_ )
+insert ( 3970 ordered_set_transition 11 10 12 1 0 0 0 f f f f f i s 2 0 2281 "2281 2276" _null_ _null_ _null_ _null_ _null_ ordered_set_transition _null_ _null_ _null_ )
+insert ( 3971 ordered_set_transition_multi 11 10 12 1 0 2276 0 f f f f f i s 2 0 2281 "2281 2276" "{2281,2276}" "{i,v}" _null_ _null_ _null_ ordered_set_transition_multi _null_ _null_ _null_ )
+insert ( 3972 percentile_disc 11 10 12 1 0 0 0 a f f f f i s 2 0 2283 "701 2283" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3973 percentile_disc_final 11 10 12 1 0 0 0 f f f f f i s 3 0 2283 "2281 701 2283" _null_ _null_ _null_ _null_ _null_ percentile_disc_final _null_ _null_ _null_ )
+insert ( 3974 percentile_cont 11 10 12 1 0 0 0 a f f f f i s 2 0 701 "701 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3975 percentile_cont_float8_final 11 10 12 1 0 0 0 f f f f f i s 2 0 701 "2281 701" _null_ _null_ _null_ _null_ _null_ percentile_cont_float8_final _null_ _null_ _null_ )
+insert ( 3976 percentile_cont 11 10 12 1 0 0 0 a f f f f i s 2 0 1186 "701 1186" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3977 percentile_cont_interval_final 11 10 12 1 0 0 0 f f f f f i s 2 0 1186 "2281 701" _null_ _null_ _null_ _null_ _null_ percentile_cont_interval_final _null_ _null_ _null_ )
+insert ( 3978 percentile_disc 11 10 12 1 0 0 0 a f f f f i s 2 0 2277 "1022 2283" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3979 percentile_disc_multi_final 11 10 12 1 0 0 0 f f f f f i s 3 0 2277 "2281 1022 2283" _null_ _null_ _null_ _null_ _null_ percentile_disc_multi_final _null_ _null_ _null_ )
+insert ( 3980 percentile_cont 11 10 12 1 0 0 0 a f f f f i s 2 0 1022 "1022 701" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3981 percentile_cont_float8_multi_final 11 10 12 1 0 0 0 f f f f f i s 2 0 1022 "2281 1022" _null_ _null_ _null_ _null_ _null_ percentile_cont_float8_multi_final _null_ _null_ _null_ )
+insert ( 3982 percentile_cont 11 10 12 1 0 0 0 a f f f f i s 2 0 1187 "1022 1186" _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3983 percentile_cont_interval_multi_final 11 10 12 1 0 0 0 f f f f f i s 2 0 1187 "2281 1022" _null_ _null_ _null_ _null_ _null_ percentile_cont_interval_multi_final _null_ _null_ _null_ )
+insert ( 3984 mode 11 10 12 1 0 0 0 a f f f f i s 1 0 2283 2283 _null_ _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3985 mode_final 11 10 12 1 0 0 0 f f f f f i s 2 0 2283 "2281 2283" _null_ _null_ _null_ _null_ _null_ mode_final _null_ _null_ _null_ )
+insert ( 3986 rank 11 10 12 1 0 2276 0 a f f f f i s 1 0 20 2276 "{2276}" "{v}" _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3987 rank_final 11 10 12 1 0 2276 0 f f f f f i s 2 0 20 "2281 2276" "{2281,2276}" "{i,v}" _null_ _null_ _null_ hypothetical_rank_final _null_ _null_ _null_ )
+insert ( 3988 percent_rank 11 10 12 1 0 2276 0 a f f f f i s 1 0 701 2276 "{2276}" "{v}" _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3989 percent_rank_final 11 10 12 1 0 2276 0 f f f f f i s 2 0 701 "2281 2276" "{2281,2276}" "{i,v}" _null_ _null_ _null_ hypothetical_percent_rank_final _null_ _null_ _null_ )
+insert ( 3990 cume_dist 11 10 12 1 0 2276 0 a f f f f i s 1 0 701 2276 "{2276}" "{v}" _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3991 cume_dist_final 11 10 12 1 0 2276 0 f f f f f i s 2 0 701 "2281 2276" "{2281,2276}" "{i,v}" _null_ _null_ _null_ hypothetical_cume_dist_final _null_ _null_ _null_ )
+insert ( 3992 dense_rank 11 10 12 1 0 2276 0 a f f f f i s 1 0 20 2276 "{2276}" "{v}" _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ )
+insert ( 3993 dense_rank_final 11 10 12 1 0 2276 0 f f f f f i s 2 0 20 "2281 2276" "{2281,2276}" "{i,v}" _null_ _null_ _null_ hypothetical_dense_rank_final _null_ _null_ _null_ )
+insert ( 3582 binary_upgrade_set_next_pg_type_oid 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_next_pg_type_oid _null_ _null_ _null_ )
+insert ( 3584 binary_upgrade_set_next_array_pg_type_oid 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_next_array_pg_type_oid _null_ _null_ _null_ )
+insert ( 3585 binary_upgrade_set_next_toast_pg_type_oid 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_next_toast_pg_type_oid _null_ _null_ _null_ )
+insert ( 3586 binary_upgrade_set_next_heap_pg_class_oid 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_next_heap_pg_class_oid _null_ _null_ _null_ )
+insert ( 3587 binary_upgrade_set_next_index_pg_class_oid 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_next_index_pg_class_oid _null_ _null_ _null_ )
+insert ( 3588 binary_upgrade_set_next_toast_pg_class_oid 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_next_toast_pg_class_oid _null_ _null_ _null_ )
+insert ( 3589 binary_upgrade_set_next_pg_enum_oid 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_next_pg_enum_oid _null_ _null_ _null_ )
+insert ( 3590 binary_upgrade_set_next_pg_authid_oid 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 26 _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_next_pg_authid_oid _null_ _null_ _null_ )
+insert ( 3591 binary_upgrade_create_empty_extension 11 10 12 1 0 0 0 f f f f f v u 7 0 2278 "25 25 16 25 1028 1009 1009" _null_ _null_ _null_ _null_ _null_ binary_upgrade_create_empty_extension _null_ _null_ _null_ )
+insert ( 4083 binary_upgrade_set_record_init_privs 11 10 12 1 0 0 0 f f f t f v r 1 0 2278 16 _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_record_init_privs _null_ _null_ _null_ )
+insert ( 4101 binary_upgrade_set_missing_value 11 10 12 1 0 0 0 f f f t f v u 3 0 2278 "26 25 25" _null_ _null_ _null_ _null_ _null_ binary_upgrade_set_missing_value _null_ _null_ _null_ )
+insert ( 4302 koi8r_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ koi8r_to_mic "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4303 mic_to_koi8r 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_koi8r "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4304 iso_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ iso_to_mic "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4305 mic_to_iso 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_iso "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4306 win1251_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win1251_to_mic "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4307 mic_to_win1251 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_win1251 "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4308 win866_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win866_to_mic "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4309 mic_to_win866 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_win866 "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4310 koi8r_to_win1251 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ koi8r_to_win1251 "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4311 win1251_to_koi8r 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win1251_to_koi8r "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4312 koi8r_to_win866 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ koi8r_to_win866 "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4313 win866_to_koi8r 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win866_to_koi8r "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4314 win866_to_win1251 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win866_to_win1251 "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4315 win1251_to_win866 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win1251_to_win866 "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4316 iso_to_koi8r 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ iso_to_koi8r "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4317 koi8r_to_iso 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ koi8r_to_iso "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4318 iso_to_win1251 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ iso_to_win1251 "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4319 win1251_to_iso 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win1251_to_iso "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4320 iso_to_win866 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ iso_to_win866 "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4321 win866_to_iso 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win866_to_iso "$libdir/cyrillic_and_mic" _null_ _null_ )
+insert ( 4322 euc_cn_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_cn_to_mic "$libdir/euc_cn_and_mic" _null_ _null_ )
+insert ( 4323 mic_to_euc_cn 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_euc_cn "$libdir/euc_cn_and_mic" _null_ _null_ )
+insert ( 4324 euc_jp_to_sjis 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_jp_to_sjis "$libdir/euc_jp_and_sjis" _null_ _null_ )
+insert ( 4325 sjis_to_euc_jp 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ sjis_to_euc_jp "$libdir/euc_jp_and_sjis" _null_ _null_ )
+insert ( 4326 euc_jp_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_jp_to_mic "$libdir/euc_jp_and_sjis" _null_ _null_ )
+insert ( 4327 sjis_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ sjis_to_mic "$libdir/euc_jp_and_sjis" _null_ _null_ )
+insert ( 4328 mic_to_euc_jp 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_euc_jp "$libdir/euc_jp_and_sjis" _null_ _null_ )
+insert ( 4329 mic_to_sjis 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_sjis "$libdir/euc_jp_and_sjis" _null_ _null_ )
+insert ( 4330 euc_kr_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_kr_to_mic "$libdir/euc_kr_and_mic" _null_ _null_ )
+insert ( 4331 mic_to_euc_kr 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_euc_kr "$libdir/euc_kr_and_mic" _null_ _null_ )
+insert ( 4332 euc_tw_to_big5 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_tw_to_big5 "$libdir/euc_tw_and_big5" _null_ _null_ )
+insert ( 4333 big5_to_euc_tw 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ big5_to_euc_tw "$libdir/euc_tw_and_big5" _null_ _null_ )
+insert ( 4334 euc_tw_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_tw_to_mic "$libdir/euc_tw_and_big5" _null_ _null_ )
+insert ( 4335 big5_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ big5_to_mic "$libdir/euc_tw_and_big5" _null_ _null_ )
+insert ( 4336 mic_to_euc_tw 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_euc_tw "$libdir/euc_tw_and_big5" _null_ _null_ )
+insert ( 4337 mic_to_big5 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_big5 "$libdir/euc_tw_and_big5" _null_ _null_ )
+insert ( 4338 latin2_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ latin2_to_mic "$libdir/latin2_and_win1250" _null_ _null_ )
+insert ( 4339 mic_to_latin2 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_latin2 "$libdir/latin2_and_win1250" _null_ _null_ )
+insert ( 4340 win1250_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win1250_to_mic "$libdir/latin2_and_win1250" _null_ _null_ )
+insert ( 4341 mic_to_win1250 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_win1250 "$libdir/latin2_and_win1250" _null_ _null_ )
+insert ( 4342 latin2_to_win1250 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ latin2_to_win1250 "$libdir/latin2_and_win1250" _null_ _null_ )
+insert ( 4343 win1250_to_latin2 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win1250_to_latin2 "$libdir/latin2_and_win1250" _null_ _null_ )
+insert ( 4344 latin1_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ latin1_to_mic "$libdir/latin_and_mic" _null_ _null_ )
+insert ( 4345 mic_to_latin1 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_latin1 "$libdir/latin_and_mic" _null_ _null_ )
+insert ( 4346 latin3_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ latin3_to_mic "$libdir/latin_and_mic" _null_ _null_ )
+insert ( 4347 mic_to_latin3 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_latin3 "$libdir/latin_and_mic" _null_ _null_ )
+insert ( 4348 latin4_to_mic 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ latin4_to_mic "$libdir/latin_and_mic" _null_ _null_ )
+insert ( 4349 mic_to_latin4 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ mic_to_latin4 "$libdir/latin_and_mic" _null_ _null_ )
+insert ( 4352 big5_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ big5_to_utf8 "$libdir/utf8_and_big5" _null_ _null_ )
+insert ( 4353 utf8_to_big5 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_big5 "$libdir/utf8_and_big5" _null_ _null_ )
+insert ( 4354 utf8_to_koi8r 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_koi8r "$libdir/utf8_and_cyrillic" _null_ _null_ )
+insert ( 4355 koi8r_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ koi8r_to_utf8 "$libdir/utf8_and_cyrillic" _null_ _null_ )
+insert ( 4356 utf8_to_koi8u 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_koi8u "$libdir/utf8_and_cyrillic" _null_ _null_ )
+insert ( 4357 koi8u_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ koi8u_to_utf8 "$libdir/utf8_and_cyrillic" _null_ _null_ )
+insert ( 4358 utf8_to_win 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_win "$libdir/utf8_and_win" _null_ _null_ )
+insert ( 4359 win_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ win_to_utf8 "$libdir/utf8_and_win" _null_ _null_ )
+insert ( 4360 euc_cn_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_cn_to_utf8 "$libdir/utf8_and_euc_cn" _null_ _null_ )
+insert ( 4361 utf8_to_euc_cn 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_euc_cn "$libdir/utf8_and_euc_cn" _null_ _null_ )
+insert ( 4362 euc_jp_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_jp_to_utf8 "$libdir/utf8_and_euc_jp" _null_ _null_ )
+insert ( 4363 utf8_to_euc_jp 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_euc_jp "$libdir/utf8_and_euc_jp" _null_ _null_ )
+insert ( 4364 euc_kr_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_kr_to_utf8 "$libdir/utf8_and_euc_kr" _null_ _null_ )
+insert ( 4365 utf8_to_euc_kr 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_euc_kr "$libdir/utf8_and_euc_kr" _null_ _null_ )
+insert ( 4366 euc_tw_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_tw_to_utf8 "$libdir/utf8_and_euc_tw" _null_ _null_ )
+insert ( 4367 utf8_to_euc_tw 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_euc_tw "$libdir/utf8_and_euc_tw" _null_ _null_ )
+insert ( 4368 gb18030_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ gb18030_to_utf8 "$libdir/utf8_and_gb18030" _null_ _null_ )
+insert ( 4369 utf8_to_gb18030 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_gb18030 "$libdir/utf8_and_gb18030" _null_ _null_ )
+insert ( 4370 gbk_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ gbk_to_utf8 "$libdir/utf8_and_gbk" _null_ _null_ )
+insert ( 4371 utf8_to_gbk 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_gbk "$libdir/utf8_and_gbk" _null_ _null_ )
+insert ( 4372 utf8_to_iso8859 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_iso8859 "$libdir/utf8_and_iso8859" _null_ _null_ )
+insert ( 4373 iso8859_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ iso8859_to_utf8 "$libdir/utf8_and_iso8859" _null_ _null_ )
+insert ( 4374 iso8859_1_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ iso8859_1_to_utf8 "$libdir/utf8_and_iso8859_1" _null_ _null_ )
+insert ( 4375 utf8_to_iso8859_1 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_iso8859_1 "$libdir/utf8_and_iso8859_1" _null_ _null_ )
+insert ( 4376 johab_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ johab_to_utf8 "$libdir/utf8_and_johab" _null_ _null_ )
+insert ( 4377 utf8_to_johab 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_johab "$libdir/utf8_and_johab" _null_ _null_ )
+insert ( 4378 sjis_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ sjis_to_utf8 "$libdir/utf8_and_sjis" _null_ _null_ )
+insert ( 4379 utf8_to_sjis 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_sjis "$libdir/utf8_and_sjis" _null_ _null_ )
+insert ( 4380 uhc_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ uhc_to_utf8 "$libdir/utf8_and_uhc" _null_ _null_ )
+insert ( 4381 utf8_to_uhc 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_uhc "$libdir/utf8_and_uhc" _null_ _null_ )
+insert ( 4382 euc_jis_2004_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_jis_2004_to_utf8 "$libdir/utf8_and_euc2004" _null_ _null_ )
+insert ( 4383 utf8_to_euc_jis_2004 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_euc_jis_2004 "$libdir/utf8_and_euc2004" _null_ _null_ )
+insert ( 4384 shift_jis_2004_to_utf8 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ shift_jis_2004_to_utf8 "$libdir/utf8_and_sjis2004" _null_ _null_ )
+insert ( 4385 utf8_to_shift_jis_2004 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ utf8_to_shift_jis_2004 "$libdir/utf8_and_sjis2004" _null_ _null_ )
+insert ( 4386 euc_jis_2004_to_shift_jis_2004 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ euc_jis_2004_to_shift_jis_2004 "$libdir/euc2004_sjis2004" _null_ _null_ )
+insert ( 4387 shift_jis_2004_to_euc_jis_2004 11 10 13 1 0 0 0 f f f t f i s 5 0 2278 "23 23 2275 2281 23" _null_ _null_ _null_ _null_ _null_ shift_jis_2004_to_euc_jis_2004 "$libdir/euc2004_sjis2004" _null_ _null_ )
+insert ( 5040 matchingsel 11 10 12 1 0 0 0 f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ matchingsel _null_ _null_ _null_ )
+insert ( 5041 matchingjoinsel 11 10 12 1 0 0 0 f f f t f s s 5 0 701 "2281 26 2281 21 2281" _null_ _null_ _null_ _null_ _null_ matchingjoinsel _null_ _null_ _null_ )
+insert ( 6003 pg_replication_origin_create 11 10 12 1 0 0 0 f f f t f v u 1 0 26 25 _null_ _null_ _null_ _null_ _null_ pg_replication_origin_create _null_ _null_ _null_ )
+insert ( 6004 pg_replication_origin_drop 11 10 12 1 0 0 0 f f f t f v u 1 0 2278 25 _null_ _null_ _null_ _null_ _null_ pg_replication_origin_drop _null_ _null_ _null_ )
+insert ( 6005 pg_replication_origin_oid 11 10 12 1 0 0 0 f f f t f s s 1 0 26 25 _null_ _null_ _null_ _null_ _null_ pg_replication_origin_oid _null_ _null_ _null_ )
+insert ( 6006 pg_replication_origin_session_setup 11 10 12 1 0 0 0 f f f t f v u 1 0 2278 25 _null_ _null_ _null_ _null_ _null_ pg_replication_origin_session_setup _null_ _null_ _null_ )
+insert ( 6007 pg_replication_origin_session_reset 11 10 12 1 0 0 0 f f f t f v u 0 0 2278 "" _null_ _null_ _null_ _null_ _null_ pg_replication_origin_session_reset _null_ _null_ _null_ )
+insert ( 6008 pg_replication_origin_session_is_setup 11 10 12 1 0 0 0 f f f t f v r 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_replication_origin_session_is_setup _null_ _null_ _null_ )
+insert ( 6009 pg_replication_origin_session_progress 11 10 12 1 0 0 0 f f f t f v u 1 0 3220 16 _null_ _null_ _null_ _null_ _null_ pg_replication_origin_session_progress _null_ _null_ _null_ )
+insert ( 6010 pg_replication_origin_xact_setup 11 10 12 1 0 0 0 f f f t f v r 2 0 2278 "3220 1184" _null_ _null_ _null_ _null_ _null_ pg_replication_origin_xact_setup _null_ _null_ _null_ )
+insert ( 6011 pg_replication_origin_xact_reset 11 10 12 1 0 0 0 f f f t f v r 0 0 2278 "" _null_ _null_ _null_ _null_ _null_ pg_replication_origin_xact_reset _null_ _null_ _null_ )
+insert ( 6012 pg_replication_origin_advance 11 10 12 1 0 0 0 f f f t f v u 2 0 2278 "25 3220" _null_ _null_ _null_ _null_ _null_ pg_replication_origin_advance _null_ _null_ _null_ )
+insert ( 6013 pg_replication_origin_progress 11 10 12 1 0 0 0 f f f t f v u 2 0 3220 "25 16" _null_ _null_ _null_ _null_ _null_ pg_replication_origin_progress _null_ _null_ _null_ )
+insert ( 6014 pg_show_replication_origin_status 11 10 12 1 100 0 0 f f f f t v r 0 0 2249 "" "{26,25,3220,3220}" "{o,o,o,o}" "{local_id, external_id, remote_lsn, local_lsn}" _null_ _null_ pg_show_replication_origin_status _null_ _null_ _null_ )
+insert ( 6119 pg_get_publication_tables 11 10 12 1 1000 0 0 f f f t t s s 1 0 26 25 "{25,26}" "{i,o}" "{pubname,relid}" _null_ _null_ pg_get_publication_tables _null_ _null_ _null_ )
+insert ( 6121 pg_relation_is_publishable 11 10 12 1 0 0 0 f f f t f s s 1 0 16 2205 _null_ _null_ _null_ _null_ _null_ pg_relation_is_publishable _null_ _null_ _null_ )
+insert ( 3298 row_security_active 11 10 12 1 0 0 0 f f f t f s s 1 0 16 26 _null_ _null_ _null_ _null_ _null_ row_security_active _null_ _null_ _null_ )
+insert ( 3299 row_security_active 11 10 12 1 0 0 0 f f f t f s s 1 0 16 25 _null_ _null_ _null_ _null_ _null_ row_security_active_name _null_ _null_ _null_ )
+insert ( 3400 pg_config 11 10 12 1 23 0 0 f f f t t s r 0 0 2249 "" "{25,25}" "{o,o}" "{name,setting}" _null_ _null_ pg_config _null_ _null_ _null_ )
+insert ( 3441 pg_control_system 11 10 12 1 0 0 0 f f f t f v s 0 0 2249 "" "{23,23,20,1184}" "{o,o,o,o}" "{pg_control_version,catalog_version_no,system_identifier,pg_control_last_modified}" _null_ _null_ pg_control_system _null_ _null_ _null_ )
+insert ( 3442 pg_control_checkpoint 11 10 12 1 0 0 0 f f f t f v s 0 0 2249 "" "{3220,3220,25,23,23,16,25,26,28,28,28,26,28,28,26,28,28,1184}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{checkpoint_lsn,redo_lsn,redo_wal_file,timeline_id,prev_timeline_id,full_page_writes,next_xid,next_oid,next_multixact_id,next_multi_offset,oldest_xid,oldest_xid_dbid,oldest_active_xid,oldest_multi_xid,oldest_multi_dbid,oldest_commit_ts_xid,newest_commit_ts_xid,checkpoint_time}" _null_ _null_ pg_control_checkpoint _null_ _null_ _null_ )
+insert ( 3443 pg_control_recovery 11 10 12 1 0 0 0 f f f t f v s 0 0 2249 "" "{3220,23,3220,3220,16}" "{o,o,o,o,o}" "{min_recovery_end_lsn,min_recovery_end_timeline,backup_start_lsn,backup_end_lsn,end_of_backup_record_required}" _null_ _null_ pg_control_recovery _null_ _null_ _null_ )
+insert ( 3444 pg_control_init 11 10 12 1 0 0 0 f f f t f v s 0 0 2249 "" "{23,23,23,23,23,23,23,23,23,16,23}" "{o,o,o,o,o,o,o,o,o,o,o}" "{max_data_alignment,database_block_size,blocks_per_segment,wal_block_size,bytes_per_wal_segment,max_identifier_length,max_index_columns,max_toast_chunk_size,large_object_chunk_size,float8_pass_by_value,data_page_checksum_version}" _null_ _null_ pg_control_init _null_ _null_ _null_ )
+insert ( 3445 pg_import_system_collations 11 10 12 100 0 0 0 f f f t f v u 1 0 23 4089 _null_ _null_ _null_ _null_ _null_ pg_import_system_collations _null_ _null_ _null_ )
+insert ( 3448 pg_collation_actual_version 11 10 12 100 0 0 0 f f f t f v s 1 0 25 26 _null_ _null_ _null_ _null_ _null_ pg_collation_actual_version _null_ _null_ _null_ )
+insert ( 3353 pg_ls_logdir 11 10 12 10 20 0 0 f f f t t v s 0 0 2249 "" "{25,20,1184}" "{o,o,o}" "{name,size,modification}" _null_ _null_ pg_ls_logdir _null_ _null_ _null_ )
+insert ( 3354 pg_ls_waldir 11 10 12 10 20 0 0 f f f t t v s 0 0 2249 "" "{25,20,1184}" "{o,o,o}" "{name,size,modification}" _null_ _null_ pg_ls_waldir _null_ _null_ _null_ )
+insert ( 5031 pg_ls_archive_statusdir 11 10 12 10 20 0 0 f f f t t v s 0 0 2249 "" "{25,20,1184}" "{o,o,o}" "{name,size,modification}" _null_ _null_ pg_ls_archive_statusdir _null_ _null_ _null_ )
+insert ( 5029 pg_ls_tmpdir 11 10 12 10 20 0 0 f f f t t v s 0 0 2249 "" "{25,20,1184}" "{o,o,o}" "{name,size,modification}" _null_ _null_ pg_ls_tmpdir_noargs _null_ _null_ _null_ )
+insert ( 5030 pg_ls_tmpdir 11 10 12 10 20 0 0 f f f t t v s 1 0 2249 26 "{26,25,20,1184}" "{i,o,o,o}" "{tablespace,name,size,modification}" _null_ _null_ pg_ls_tmpdir_1arg _null_ _null_ _null_ )
+insert ( 5028 satisfies_hash_partition 11 10 12 1 0 2276 0 f f f f f i s 4 0 16 "26 23 23 2276" _null_ "{i,i,i,v}" _null_ _null_ _null_ satisfies_hash_partition _null_ _null_ _null_ )
+insert ( 3423 pg_partition_tree 11 10 12 1 1000 0 0 f f f t t v s 1 0 2249 2205 "{2205,2205,2205,16,23}" "{i,o,o,o,o}" "{rootrelid,relid,parentrelid,isleaf,level}" _null_ _null_ pg_partition_tree _null_ _null_ _null_ )
+insert ( 3425 pg_partition_ancestors 11 10 12 1 10 0 0 f f f t t v s 1 0 2205 2205 "{2205,2205}" "{i,o}" "{partitionid,relid}" _null_ _null_ pg_partition_ancestors _null_ _null_ _null_ )
+insert ( 3424 pg_partition_root 11 10 12 1 0 0 0 f f f t f i s 1 0 2205 2205 _null_ _null_ _null_ _null_ _null_ pg_partition_root _null_ _null_ _null_ )
+insert ( 4350 normalize 11 10 12 1 0 0 0 f f f t f i s 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ unicode_normalize_func _null_ _null_ _null_ )
+insert ( 4351 is_normalized 11 10 12 1 0 0 0 f f f t f i s 2 0 16 "25 25" _null_ _null_ _null_ _null_ _null_ unicode_is_normalized _null_ _null_ _null_ )
+close pg_proc
+create pg_type 1247 bootstrap rowtype_oid 71
+ (
+ oid = oid ,
+ typname = name ,
+ typnamespace = oid ,
+ typowner = oid ,
+ typlen = int2 ,
+ typbyval = bool ,
+ typtype = char ,
+ typcategory = char ,
+ typispreferred = bool ,
+ typisdefined = bool ,
+ typdelim = char ,
+ typrelid = oid ,
+ typelem = oid ,
+ typarray = oid ,
+ typinput = regproc ,
+ typoutput = regproc ,
+ typreceive = regproc ,
+ typsend = regproc ,
+ typmodin = regproc ,
+ typmodout = regproc ,
+ typanalyze = regproc ,
+ typalign = char ,
+ typstorage = char ,
+ typnotnull = bool ,
+ typbasetype = oid ,
+ typtypmod = int4 ,
+ typndims = int4 ,
+ typcollation = oid ,
+ typdefaultbin = pg_node_tree ,
+ typdefault = text ,
+ typacl = _aclitem
+ )
+insert ( 16 bool 11 10 1 t b B t t "," 0 0 1000 1242 1243 2436 2437 - - - c p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 17 bytea 11 10 -1 f b U f t "," 0 0 1001 1244 31 2412 2413 - - - i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 18 char 11 10 1 t b S f t "," 0 0 1002 1245 33 2434 2435 - - - c p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 19 name 11 10 NAMEDATALEN f b S f t "," 0 18 1003 34 35 2422 2423 - - - c p f 0 -1 0 950 _null_ _null_ _null_ )
+insert ( 20 int8 11 10 8 FLOAT8PASSBYVAL b N f t "," 0 0 1016 460 461 2408 2409 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 21 int2 11 10 2 t b N f t "," 0 0 1005 38 39 2404 2405 - - - s p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 22 int2vector 11 10 -1 f b A f t "," 0 21 1006 40 41 2410 2411 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 23 int4 11 10 4 t b N f t "," 0 0 1007 42 43 2406 2407 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 24 regproc 11 10 4 t b N f t "," 0 0 1008 44 45 2444 2445 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 25 text 11 10 -1 f b S t t "," 0 0 1009 46 47 2414 2415 - - - i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 26 oid 11 10 4 t b N t t "," 0 0 1028 1798 1799 2418 2419 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 27 tid 11 10 6 f b U f t "," 0 0 1010 48 49 2438 2439 - - - s p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 28 xid 11 10 4 t b U f t "," 0 0 1011 50 51 2440 2441 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 29 cid 11 10 4 t b U f t "," 0 0 1012 52 53 2442 2443 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 30 oidvector 11 10 -1 f b A f t "," 0 26 1013 54 55 2420 2421 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 71 pg_type 11 10 -1 f c C f t "," 1247 0 0 2290 2291 2402 2403 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 75 pg_attribute 11 10 -1 f c C f t "," 1249 0 0 2290 2291 2402 2403 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 81 pg_proc 11 10 -1 f c C f t "," 1255 0 0 2290 2291 2402 2403 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 83 pg_class 11 10 -1 f c C f t "," 1259 0 0 2290 2291 2402 2403 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 114 json 11 10 -1 f b U f t "," 0 0 199 321 322 323 324 - - - i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 142 xml 11 10 -1 f b U f t "," 0 0 143 2893 2894 2898 2899 - - - i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 194 pg_node_tree 11 10 -1 f b S f t "," 0 0 0 195 196 197 198 - - - i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 3361 pg_ndistinct 11 10 -1 f b S f t "," 0 0 0 3355 3356 3357 3358 - - - i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 3402 pg_dependencies 11 10 -1 f b S f t "," 0 0 0 3404 3405 3406 3407 - - - i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 5017 pg_mcv_list 11 10 -1 f b S f t "," 0 0 0 5018 5019 5020 5021 - - - i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 32 pg_ddl_command 11 10 SIZEOF_POINTER t p P f t "," 0 0 0 86 87 88 90 - - - ALIGNOF_POINTER p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 5069 xid8 11 10 8 FLOAT8PASSBYVAL b U f t "," 0 0 271 5070 5081 5082 5083 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 600 point 11 10 16 f b G f t "," 0 701 1017 117 118 2428 2429 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 601 lseg 11 10 32 f b G f t "," 0 600 1018 119 120 2480 2481 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 602 path 11 10 -1 f b G f t "," 0 0 1019 121 122 2482 2483 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 603 box 11 10 32 f b G f t ";" 0 600 1020 123 124 2484 2485 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 604 polygon 11 10 -1 f b G f t "," 0 0 1027 347 348 2486 2487 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 628 line 11 10 24 f b G f t "," 0 701 629 1490 1491 2488 2489 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 700 float4 11 10 4 t b N f t "," 0 0 1021 200 201 2424 2425 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 701 float8 11 10 8 FLOAT8PASSBYVAL b N t t "," 0 0 1022 214 215 2426 2427 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 705 unknown 11 10 -2 f p X f t "," 0 0 0 109 110 2416 2417 - - - c p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 718 circle 11 10 24 f b G f t "," 0 0 719 1450 1451 2490 2491 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 790 money 11 10 8 FLOAT8PASSBYVAL b N f t "," 0 0 791 886 887 2492 2493 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 829 macaddr 11 10 6 f b U f t "," 0 0 1040 436 437 2494 2495 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 869 inet 11 10 -1 f b I t t "," 0 0 1041 910 911 2496 2497 - - - i m f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 650 cidr 11 10 -1 f b I f t "," 0 0 651 1267 1427 2498 2499 - - - i m f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 774 macaddr8 11 10 8 f b U f t "," 0 0 775 4110 4111 3446 3447 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1033 aclitem 11 10 12 f b U f t "," 0 0 1034 1031 1032 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1042 bpchar 11 10 -1 f b S f t "," 0 0 1014 1044 1045 2430 2431 2913 2914 - i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 1043 varchar 11 10 -1 f b S f t "," 0 0 1015 1046 1047 2432 2433 2915 2916 - i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 1082 date 11 10 4 t b D f t "," 0 0 1182 1084 1085 2468 2469 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1083 time 11 10 8 FLOAT8PASSBYVAL b D f t "," 0 0 1183 1143 1144 2470 2471 2909 2910 - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1114 timestamp 11 10 8 FLOAT8PASSBYVAL b D f t "," 0 0 1115 1312 1313 2474 2475 2905 2906 - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1184 timestamptz 11 10 8 FLOAT8PASSBYVAL b D t t "," 0 0 1185 1150 1151 2476 2477 2907 2908 - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1186 interval 11 10 16 f b T t t "," 0 0 1187 1160 1161 2478 2479 2903 2904 - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1266 timetz 11 10 12 f b D f t "," 0 0 1270 1350 1351 2472 2473 2911 2912 - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1560 bit 11 10 -1 f b V f t "," 0 0 1561 1564 1565 2456 2457 2919 2920 - i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1562 varbit 11 10 -1 f b V t t "," 0 0 1563 1579 1580 2458 2459 2902 2921 - i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1700 numeric 11 10 -1 f b N f t "," 0 0 1231 1701 1702 2460 2461 2917 2918 - i m f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1790 refcursor 11 10 -1 f b U f t "," 0 0 2201 46 47 2414 2415 - - - i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2202 regprocedure 11 10 4 t b N f t "," 0 0 2207 2212 2213 2446 2447 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2203 regoper 11 10 4 t b N f t "," 0 0 2208 2214 2215 2448 2449 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2204 regoperator 11 10 4 t b N f t "," 0 0 2209 2216 2217 2450 2451 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2205 regclass 11 10 4 t b N f t "," 0 0 2210 2218 2219 2452 2453 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 4191 regcollation 11 10 4 t b N f t "," 0 0 4192 4193 4194 4196 4197 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2206 regtype 11 10 4 t b N f t "," 0 0 2211 2220 2221 2454 2455 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 4096 regrole 11 10 4 t b N f t "," 0 0 4097 4098 4092 4094 4095 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 4089 regnamespace 11 10 4 t b N f t "," 0 0 4090 4084 4085 4087 4088 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2950 uuid 11 10 16 f b U f t "," 0 0 2951 2952 2953 2961 2962 - - - c p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3220 pg_lsn 11 10 8 FLOAT8PASSBYVAL b U f t "," 0 0 3221 3229 3230 3238 3239 - - - d p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3614 tsvector 11 10 -1 f b U f t "," 0 0 3643 3610 3611 3639 3638 - - 3688 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3642 gtsvector 11 10 -1 f b U f t "," 0 0 3644 3646 3647 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3615 tsquery 11 10 -1 f b U f t "," 0 0 3645 3612 3613 3641 3640 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3734 regconfig 11 10 4 t b N f t "," 0 0 3735 3736 3737 3738 3739 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3769 regdictionary 11 10 4 t b N f t "," 0 0 3770 3771 3772 3773 3774 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3802 jsonb 11 10 -1 f b U f t "," 0 0 3807 3806 3804 3805 3803 - - - i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 4072 jsonpath 11 10 -1 f b U f t "," 0 0 4073 4001 4003 4002 4004 - - - i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2970 txid_snapshot 11 10 -1 f b U f t "," 0 0 2949 2939 2940 2941 2942 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 5038 pg_snapshot 11 10 -1 f b U f t "," 0 0 5039 5055 5056 5057 5058 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3904 int4range 11 10 -1 f r R f t "," 0 0 3905 3834 3835 3836 3837 - - 3916 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3906 numrange 11 10 -1 f r R f t "," 0 0 3907 3834 3835 3836 3837 - - 3916 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3908 tsrange 11 10 -1 f r R f t "," 0 0 3909 3834 3835 3836 3837 - - 3916 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3910 tstzrange 11 10 -1 f r R f t "," 0 0 3911 3834 3835 3836 3837 - - 3916 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3912 daterange 11 10 -1 f r R f t "," 0 0 3913 3834 3835 3836 3837 - - 3916 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3926 int8range 11 10 -1 f r R f t "," 0 0 3927 3834 3835 3836 3837 - - 3916 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2249 record 11 10 -1 f p P f t "," 0 0 2287 2290 2291 2402 2403 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2287 _record 11 10 -1 f p P f t "," 0 2249 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2275 cstring 11 10 -2 f p P f t "," 0 0 1263 2292 2293 2500 2501 - - - c p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2276 any 11 10 4 t p P f t "," 0 0 0 2294 2295 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2277 anyarray 11 10 -1 f p P f t "," 0 0 0 2296 2297 2502 2503 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2278 void 11 10 4 t p P f t "," 0 0 0 2298 2299 3120 3121 - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2279 trigger 11 10 4 t p P f t "," 0 0 0 2300 2301 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3838 event_trigger 11 10 4 t p P f t "," 0 0 0 3594 3595 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2280 language_handler 11 10 4 t p P f t "," 0 0 0 2302 2303 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2281 internal 11 10 SIZEOF_POINTER t p P f t "," 0 0 0 2304 2305 - - - - - ALIGNOF_POINTER p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2283 anyelement 11 10 4 t p P f t "," 0 0 0 2312 2313 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2776 anynonarray 11 10 4 t p P f t "," 0 0 0 2777 2778 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3500 anyenum 11 10 4 t p P f t "," 0 0 0 3504 3505 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3115 fdw_handler 11 10 4 t p P f t "," 0 0 0 3116 3117 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 325 index_am_handler 11 10 4 t p P f t "," 0 0 0 326 327 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3310 tsm_handler 11 10 4 t p P f t "," 0 0 0 3311 3312 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 269 table_am_handler 11 10 4 t p P f t "," 0 0 0 267 268 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3831 anyrange 11 10 -1 f p P f t "," 0 0 0 3832 3833 - - - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 5077 anycompatible 11 10 4 t p P f t "," 0 0 0 5086 5087 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 5078 anycompatiblearray 11 10 -1 f p P f t "," 0 0 0 5088 5089 5090 5091 - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 5079 anycompatiblenonarray 11 10 4 t p P f t "," 0 0 0 5092 5093 - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 5080 anycompatiblerange 11 10 -1 f p P f t "," 0 0 0 5094 5095 - - - - - d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1000 _bool 11 10 -1 f b A f t "," 0 16 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1001 _bytea 11 10 -1 f b A f t "," 0 17 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1002 _char 11 10 -1 f b A f t "," 0 18 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1003 _name 11 10 -1 f b A f t "," 0 19 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 950 _null_ _null_ _null_ )
+insert ( 1016 _int8 11 10 -1 f b A f t "," 0 20 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1005 _int2 11 10 -1 f b A f t "," 0 21 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1006 _int2vector 11 10 -1 f b A f t "," 0 22 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1007 _int4 11 10 -1 f b A f t "," 0 23 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1008 _regproc 11 10 -1 f b A f t "," 0 24 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1009 _text 11 10 -1 f b A f t "," 0 25 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 1028 _oid 11 10 -1 f b A f t "," 0 26 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1010 _tid 11 10 -1 f b A f t "," 0 27 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1011 _xid 11 10 -1 f b A f t "," 0 28 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1012 _cid 11 10 -1 f b A f t "," 0 29 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1013 _oidvector 11 10 -1 f b A f t "," 0 30 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 199 _json 11 10 -1 f b A f t "," 0 114 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 143 _xml 11 10 -1 f b A f t "," 0 142 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 271 _xid8 11 10 -1 f b A f t "," 0 5069 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1017 _point 11 10 -1 f b A f t "," 0 600 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1018 _lseg 11 10 -1 f b A f t "," 0 601 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1019 _path 11 10 -1 f b A f t "," 0 602 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1020 _box 11 10 -1 f b A f t ";" 0 603 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1027 _polygon 11 10 -1 f b A f t "," 0 604 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 629 _line 11 10 -1 f b A f t "," 0 628 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1021 _float4 11 10 -1 f b A f t "," 0 700 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1022 _float8 11 10 -1 f b A f t "," 0 701 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 719 _circle 11 10 -1 f b A f t "," 0 718 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 791 _money 11 10 -1 f b A f t "," 0 790 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1040 _macaddr 11 10 -1 f b A f t "," 0 829 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1041 _inet 11 10 -1 f b A f t "," 0 869 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 651 _cidr 11 10 -1 f b A f t "," 0 650 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 775 _macaddr8 11 10 -1 f b A f t "," 0 774 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1034 _aclitem 11 10 -1 f b A f t "," 0 1033 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1014 _bpchar 11 10 -1 f b A f t "," 0 1042 0 750 751 2400 2401 2913 2914 3816 i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 1015 _varchar 11 10 -1 f b A f t "," 0 1043 0 750 751 2400 2401 2915 2916 3816 i x f 0 -1 0 100 _null_ _null_ _null_ )
+insert ( 1182 _date 11 10 -1 f b A f t "," 0 1082 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1183 _time 11 10 -1 f b A f t "," 0 1083 0 750 751 2400 2401 2909 2910 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1115 _timestamp 11 10 -1 f b A f t "," 0 1114 0 750 751 2400 2401 2905 2906 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1185 _timestamptz 11 10 -1 f b A f t "," 0 1184 0 750 751 2400 2401 2907 2908 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1187 _interval 11 10 -1 f b A f t "," 0 1186 0 750 751 2400 2401 2903 2904 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1270 _timetz 11 10 -1 f b A f t "," 0 1266 0 750 751 2400 2401 2911 2912 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1561 _bit 11 10 -1 f b A f t "," 0 1560 0 750 751 2400 2401 2919 2920 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1563 _varbit 11 10 -1 f b A f t "," 0 1562 0 750 751 2400 2401 2902 2921 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1231 _numeric 11 10 -1 f b A f t "," 0 1700 0 750 751 2400 2401 2917 2918 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2201 _refcursor 11 10 -1 f b A f t "," 0 1790 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2207 _regprocedure 11 10 -1 f b A f t "," 0 2202 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2208 _regoper 11 10 -1 f b A f t "," 0 2203 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2209 _regoperator 11 10 -1 f b A f t "," 0 2204 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2210 _regclass 11 10 -1 f b A f t "," 0 2205 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 4192 _regcollation 11 10 -1 f b A f t "," 0 4191 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2211 _regtype 11 10 -1 f b A f t "," 0 2206 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 4097 _regrole 11 10 -1 f b A f t "," 0 4096 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 4090 _regnamespace 11 10 -1 f b A f t "," 0 4089 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2951 _uuid 11 10 -1 f b A f t "," 0 2950 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3221 _pg_lsn 11 10 -1 f b A f t "," 0 3220 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3643 _tsvector 11 10 -1 f b A f t "," 0 3614 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3644 _gtsvector 11 10 -1 f b A f t "," 0 3642 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3645 _tsquery 11 10 -1 f b A f t "," 0 3615 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3735 _regconfig 11 10 -1 f b A f t "," 0 3734 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3770 _regdictionary 11 10 -1 f b A f t "," 0 3769 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3807 _jsonb 11 10 -1 f b A f t "," 0 3802 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 4073 _jsonpath 11 10 -1 f b A f t "," 0 4072 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 2949 _txid_snapshot 11 10 -1 f b A f t "," 0 2970 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 5039 _pg_snapshot 11 10 -1 f b A f t "," 0 5038 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3905 _int4range 11 10 -1 f b A f t "," 0 3904 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3907 _numrange 11 10 -1 f b A f t "," 0 3906 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3909 _tsrange 11 10 -1 f b A f t "," 0 3908 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3911 _tstzrange 11 10 -1 f b A f t "," 0 3910 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3913 _daterange 11 10 -1 f b A f t "," 0 3912 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 3927 _int8range 11 10 -1 f b A f t "," 0 3926 0 750 751 2400 2401 - - 3816 d x f 0 -1 0 0 _null_ _null_ _null_ )
+insert ( 1263 _cstring 11 10 -1 f b A f t "," 0 2275 0 750 751 2400 2401 - - 3816 i x f 0 -1 0 0 _null_ _null_ _null_ )
+close pg_type
+create pg_attribute 1249 bootstrap rowtype_oid 75
+ (
+ attrelid = oid ,
+ attname = name ,
+ atttypid = oid ,
+ attstattarget = int4 ,
+ attlen = int2 ,
+ attnum = int2 ,
+ attndims = int4 ,
+ attcacheoff = int4 ,
+ atttypmod = int4 ,
+ attbyval = bool ,
+ attstorage = char ,
+ attalign = char ,
+ attnotnull = bool ,
+ atthasdef = bool ,
+ atthasmissing = bool ,
+ attidentity = char ,
+ attgenerated = char ,
+ attisdropped = bool ,
+ attislocal = bool ,
+ attinhcount = int4 ,
+ attcollation = oid ,
+ attacl = _aclitem ,
+ attoptions = _text ,
+ attfdwoptions = _text ,
+ attmissingval = anyarray
+ )
+insert ( 1255 oid 26 -1 4 1 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proname 19 -1 NAMEDATALEN 2 0 -1 -1 f p c t f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1255 pronamespace 26 -1 4 3 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proowner 26 -1 4 4 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 prolang 26 -1 4 5 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 procost 700 -1 4 6 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 prorows 700 -1 4 7 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 provariadic 26 -1 4 8 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 prosupport 24 -1 4 9 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 prokind 18 -1 1 10 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 prosecdef 16 -1 1 11 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proleakproof 16 -1 1 12 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proisstrict 16 -1 1 13 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proretset 16 -1 1 14 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 provolatile 18 -1 1 15 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proparallel 18 -1 1 16 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 pronargs 21 -1 2 17 0 -1 -1 t p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 pronargdefaults 21 -1 2 18 0 -1 -1 t p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 prorettype 26 -1 4 19 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proargtypes 30 -1 -1 20 1 -1 -1 f p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proallargtypes 1028 -1 -1 21 1 -1 -1 f x i f f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proargmodes 1002 -1 -1 22 1 -1 -1 f x i f f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 proargnames 1009 -1 -1 23 1 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1255 proargdefaults 194 -1 -1 24 0 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1255 protrftypes 1028 -1 -1 25 1 -1 -1 f x i f f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 prosrc 25 -1 -1 26 0 -1 -1 f x i t f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1255 probin 25 -1 -1 27 0 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1255 proconfig 1009 -1 -1 28 1 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1255 proacl 1034 -1 -1 29 1 -1 -1 f x i f f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 xmin 28 0 4 -2 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 cmin 29 0 4 -3 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 xmax 28 0 4 -4 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 cmax 29 0 4 -5 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1255 tableoid 26 0 4 -6 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 oid 26 -1 4 1 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typname 19 -1 NAMEDATALEN 2 0 -1 -1 f p c t f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1247 typnamespace 26 -1 4 3 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typowner 26 -1 4 4 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typlen 21 -1 2 5 0 -1 -1 t p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typbyval 16 -1 1 6 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typtype 18 -1 1 7 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typcategory 18 -1 1 8 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typispreferred 16 -1 1 9 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typisdefined 16 -1 1 10 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typdelim 18 -1 1 11 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typrelid 26 -1 4 12 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typelem 26 -1 4 13 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typarray 26 -1 4 14 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typinput 24 -1 4 15 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typoutput 24 -1 4 16 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typreceive 24 -1 4 17 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typsend 24 -1 4 18 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typmodin 24 -1 4 19 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typmodout 24 -1 4 20 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typanalyze 24 -1 4 21 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typalign 18 -1 1 22 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typstorage 18 -1 1 23 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typnotnull 16 -1 1 24 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typbasetype 26 -1 4 25 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typtypmod 23 -1 4 26 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typndims 23 -1 4 27 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typcollation 26 -1 4 28 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 typdefaultbin 194 -1 -1 29 0 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1247 typdefault 25 -1 -1 30 0 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1247 typacl 1034 -1 -1 31 1 -1 -1 f x i f f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 xmin 28 0 4 -2 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 cmin 29 0 4 -3 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 xmax 28 0 4 -4 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 cmax 29 0 4 -5 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1247 tableoid 26 0 4 -6 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attrelid 26 -1 4 1 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p c t f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1249 atttypid 26 -1 4 3 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attstattarget 23 -1 4 4 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attlen 21 -1 2 5 0 -1 -1 t p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attnum 21 -1 2 6 0 -1 -1 t p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attndims 23 -1 4 7 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attcacheoff 23 -1 4 8 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 atttypmod 23 -1 4 9 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attbyval 16 -1 1 10 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attstorage 18 -1 1 11 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attalign 18 -1 1 12 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attnotnull 16 -1 1 13 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 atthasdef 16 -1 1 14 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 atthasmissing 16 -1 1 15 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attidentity 18 -1 1 16 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attgenerated 18 -1 1 17 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attisdropped 16 -1 1 18 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attislocal 16 -1 1 19 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attinhcount 23 -1 4 20 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attcollation 26 -1 4 21 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attacl 1034 -1 -1 22 1 -1 -1 f x i f f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 attoptions 1009 -1 -1 23 1 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1249 attfdwoptions 1009 -1 -1 24 1 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1249 attmissingval 2277 -1 -1 25 0 -1 -1 f x d f f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 ctid 27 0 6 -1 0 -1 -1 f p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 xmin 28 0 4 -2 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 cmin 29 0 4 -3 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 xmax 28 0 4 -4 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 cmax 29 0 4 -5 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1249 tableoid 26 0 4 -6 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 oid 26 -1 4 1 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relname 19 -1 NAMEDATALEN 2 0 -1 -1 f p c t f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1259 relnamespace 26 -1 4 3 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 reltype 26 -1 4 4 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 reloftype 26 -1 4 5 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relowner 26 -1 4 6 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relam 26 -1 4 7 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relfilenode 26 -1 4 8 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 reltablespace 26 -1 4 9 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relpages 23 -1 4 10 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 reltuples 700 -1 4 11 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relallvisible 23 -1 4 12 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 reltoastrelid 26 -1 4 13 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relhasindex 16 -1 1 14 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relisshared 16 -1 1 15 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relpersistence 18 -1 1 16 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relkind 18 -1 1 17 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relnatts 21 -1 2 18 0 -1 -1 t p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relchecks 21 -1 2 19 0 -1 -1 t p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relhasrules 16 -1 1 20 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relhastriggers 16 -1 1 21 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relhassubclass 16 -1 1 22 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relrowsecurity 16 -1 1 23 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relforcerowsecurity 16 -1 1 24 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relispopulated 16 -1 1 25 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relreplident 18 -1 1 26 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relispartition 16 -1 1 27 0 -1 -1 t p c t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relrewrite 26 -1 4 28 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relfrozenxid 28 -1 4 29 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relminmxid 28 -1 4 30 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 relacl 1034 -1 -1 31 1 -1 -1 f x i f f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 reloptions 1009 -1 -1 32 1 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1259 relpartbound 194 -1 -1 33 0 -1 -1 f x i f f f "" "" f t 0 950 _null_ _null_ _null_ _null_ )
+insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 xmin 28 0 4 -2 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 cmin 29 0 4 -3 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 xmax 28 0 4 -4 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 cmax 29 0 4 -5 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+insert ( 1259 tableoid 26 0 4 -6 0 -1 -1 t p i t f f "" "" f t 0 0 _null_ _null_ _null_ _null_ )
+close pg_attribute
+create pg_class 1259 bootstrap rowtype_oid 83
+ (
+ oid = oid ,
+ relname = name ,
+ relnamespace = oid ,
+ reltype = oid ,
+ reloftype = oid ,
+ relowner = oid ,
+ relam = oid ,
+ relfilenode = oid ,
+ reltablespace = oid ,
+ relpages = int4 ,
+ reltuples = float4 ,
+ relallvisible = int4 ,
+ reltoastrelid = oid ,
+ relhasindex = bool ,
+ relisshared = bool ,
+ relpersistence = char ,
+ relkind = char ,
+ relnatts = int2 ,
+ relchecks = int2 ,
+ relhasrules = bool ,
+ relhastriggers = bool ,
+ relhassubclass = bool ,
+ relrowsecurity = bool ,
+ relforcerowsecurity = bool ,
+ relispopulated = bool ,
+ relreplident = char ,
+ relispartition = bool ,
+ relrewrite = oid ,
+ relfrozenxid = xid ,
+ relminmxid = xid ,
+ relacl = _aclitem ,
+ reloptions = _text ,
+ relpartbound = pg_node_tree
+ )
+insert ( 1247 pg_type 11 71 0 10 2 0 0 0 0 0 0 f f p r 31 0 f f f f f t n f 0 3 1 _null_ _null_ _null_ )
+insert ( 1249 pg_attribute 11 75 0 10 2 0 0 0 0 0 0 f f p r 25 0 f f f f f t n f 0 3 1 _null_ _null_ _null_ )
+insert ( 1255 pg_proc 11 81 0 10 2 0 0 0 0 0 0 f f p r 29 0 f f f f f t n f 0 3 1 _null_ _null_ _null_ )
+insert ( 1259 pg_class 11 83 0 10 2 0 0 0 0 0 0 f f p r 33 0 f f f f f t n f 0 3 1 _null_ _null_ _null_ )
+close pg_class
+create pg_attrdef 2604
+ (
+ oid = oid ,
+ adrelid = oid ,
+ adnum = int2 ,
+ adbin = pg_node_tree FORCE NOT NULL
+ )
+open pg_attrdef
+close pg_attrdef
+create pg_constraint 2606
+ (
+ oid = oid ,
+ conname = name ,
+ connamespace = oid ,
+ contype = char ,
+ condeferrable = bool ,
+ condeferred = bool ,
+ convalidated = bool ,
+ conrelid = oid ,
+ contypid = oid ,
+ conindid = oid ,
+ conparentid = oid ,
+ confrelid = oid ,
+ confupdtype = char ,
+ confdeltype = char ,
+ confmatchtype = char ,
+ conislocal = bool ,
+ coninhcount = int4 ,
+ connoinherit = bool ,
+ conkey = _int2 ,
+ confkey = _int2 ,
+ conpfeqop = _oid ,
+ conppeqop = _oid ,
+ conffeqop = _oid ,
+ conexclop = _oid ,
+ conbin = pg_node_tree
+ )
+open pg_constraint
+close pg_constraint
+create pg_inherits 2611
+ (
+ inhrelid = oid ,
+ inhparent = oid ,
+ inhseqno = int4
+ )
+open pg_inherits
+close pg_inherits
+create pg_index 2610
+ (
+ indexrelid = oid ,
+ indrelid = oid ,
+ indnatts = int2 ,
+ indnkeyatts = int2 ,
+ indisunique = bool ,
+ indisprimary = bool ,
+ indisexclusion = bool ,
+ indimmediate = bool ,
+ indisclustered = bool ,
+ indisvalid = bool ,
+ indcheckxmin = bool ,
+ indisready = bool ,
+ indislive = bool ,
+ indisreplident = bool ,
+ indkey = int2vector ,
+ indcollation = oidvector ,
+ indclass = oidvector ,
+ indoption = int2vector ,
+ indexprs = pg_node_tree ,
+ indpred = pg_node_tree
+ )
+open pg_index
+close pg_index
+create pg_operator 2617
+ (
+ oid = oid ,
+ oprname = name ,
+ oprnamespace = oid ,
+ oprowner = oid ,
+ oprkind = char ,
+ oprcanmerge = bool ,
+ oprcanhash = bool ,
+ oprleft = oid ,
+ oprright = oid ,
+ oprresult = oid ,
+ oprcom = oid ,
+ oprnegate = oid ,
+ oprcode = regproc ,
+ oprrest = regproc ,
+ oprjoin = regproc
+ )
+open pg_operator
+insert ( 15 "=" 11 10 b t t 23 20 16 416 36 852 101 105 )
+insert ( 36 "<>" 11 10 b f f 23 20 16 417 15 853 102 106 )
+insert ( 37 "<" 11 10 b f f 23 20 16 419 82 854 103 107 )
+insert ( 76 ">" 11 10 b f f 23 20 16 418 80 855 104 108 )
+insert ( 80 "<=" 11 10 b f f 23 20 16 430 76 856 336 386 )
+insert ( 82 ">=" 11 10 b f f 23 20 16 420 37 857 337 398 )
+insert ( 58 "<" 11 10 b f f 16 16 16 59 1695 56 103 107 )
+insert ( 59 ">" 11 10 b f f 16 16 16 58 1694 57 104 108 )
+insert ( 85 "<>" 11 10 b f f 16 16 16 85 91 84 102 106 )
+insert ( 91 "=" 11 10 b t t 16 16 16 91 85 60 101 105 )
+insert ( 1694 "<=" 11 10 b f f 16 16 16 1695 59 1691 336 386 )
+insert ( 1695 ">=" 11 10 b f f 16 16 16 1694 58 1692 337 398 )
+insert ( 92 "=" 11 10 b t t 18 18 16 92 630 61 101 105 )
+insert ( 93 "=" 11 10 b t t 19 19 16 93 643 62 101 105 )
+insert ( 94 "=" 11 10 b t t 21 21 16 94 519 63 101 105 )
+insert ( 95 "<" 11 10 b f f 21 21 16 520 524 64 103 107 )
+insert ( 96 "=" 11 10 b t t 23 23 16 96 518 65 101 105 )
+insert ( 97 "<" 11 10 b f f 23 23 16 521 525 66 103 107 )
+insert ( 98 "=" 11 10 b t t 25 25 16 98 531 67 101 105 )
+insert ( 3877 "^@" 11 10 b f f 25 25 16 0 0 3696 3437 3438 )
+insert ( 254 "=" 11 10 b t t 19 25 16 260 259 240 101 105 )
+insert ( 255 "<" 11 10 b f f 19 25 16 264 257 241 103 107 )
+insert ( 256 "<=" 11 10 b f f 19 25 16 263 258 242 336 386 )
+insert ( 257 ">=" 11 10 b f f 19 25 16 262 255 243 337 398 )
+insert ( 258 ">" 11 10 b f f 19 25 16 261 256 244 104 108 )
+insert ( 259 "<>" 11 10 b f f 19 25 16 265 254 245 102 106 )
+insert ( 260 "=" 11 10 b t t 25 19 16 254 265 247 101 105 )
+insert ( 261 "<" 11 10 b f f 25 19 16 258 263 248 103 107 )
+insert ( 262 "<=" 11 10 b f f 25 19 16 257 264 249 336 386 )
+insert ( 263 ">=" 11 10 b f f 25 19 16 256 261 250 337 398 )
+insert ( 264 ">" 11 10 b f f 25 19 16 255 262 251 104 108 )
+insert ( 265 "<>" 11 10 b f f 25 19 16 259 260 252 102 106 )
+insert ( 349 "||" 11 10 b f f 2277 2283 2277 0 0 378 - - )
+insert ( 374 "||" 11 10 b f f 2283 2277 2277 0 0 379 - - )
+insert ( 375 "||" 11 10 b f f 2277 2277 2277 0 0 383 - - )
+insert ( 352 "=" 11 10 b f t 28 28 16 352 3315 68 101 105 )
+insert ( 353 "=" 11 10 b f f 28 23 16 0 3316 1319 101 105 )
+insert ( 3315 "<>" 11 10 b f f 28 28 16 3315 352 3308 102 106 )
+insert ( 3316 "<>" 11 10 b f f 28 23 16 0 353 3309 102 106 )
+insert ( 5068 "=" 11 10 b t t 5069 5069 16 5068 5072 5084 101 105 )
+insert ( 5072 "<>" 11 10 b f f 5069 5069 16 5072 5068 5085 102 106 )
+insert ( 5073 "<" 11 10 b f f 5069 5069 16 5074 5076 5034 103 107 )
+insert ( 5074 ">" 11 10 b f f 5069 5069 16 5073 5075 5035 104 108 )
+insert ( 5075 "<=" 11 10 b f f 5069 5069 16 5076 5074 5036 336 386 )
+insert ( 5076 ">=" 11 10 b f f 5069 5069 16 5075 5073 5037 337 398 )
+insert ( 388 "!" 11 10 r f f 20 0 1700 0 0 111 - - )
+insert ( 389 "!!" 11 10 l f f 0 20 1700 0 0 111 - - )
+insert ( 385 "=" 11 10 b f t 29 29 16 385 0 69 101 105 )
+insert ( 387 "=" 11 10 b t t 27 27 16 387 402 1292 101 105 )
+insert ( 402 "<>" 11 10 b f f 27 27 16 402 387 1265 102 106 )
+insert ( 2799 "<" 11 10 b f f 27 27 16 2800 2802 2791 103 107 )
+insert ( 2800 ">" 11 10 b f f 27 27 16 2799 2801 2790 104 108 )
+insert ( 2801 "<=" 11 10 b f f 27 27 16 2802 2800 2793 336 386 )
+insert ( 2802 ">=" 11 10 b f f 27 27 16 2801 2799 2792 337 398 )
+insert ( 410 "=" 11 10 b t t 20 20 16 410 411 467 101 105 )
+insert ( 411 "<>" 11 10 b f f 20 20 16 411 410 468 102 106 )
+insert ( 412 "<" 11 10 b f f 20 20 16 413 415 469 103 107 )
+insert ( 413 ">" 11 10 b f f 20 20 16 412 414 470 104 108 )
+insert ( 414 "<=" 11 10 b f f 20 20 16 415 413 471 336 386 )
+insert ( 415 ">=" 11 10 b f f 20 20 16 414 412 472 337 398 )
+insert ( 416 "=" 11 10 b t t 20 23 16 15 417 474 101 105 )
+insert ( 417 "<>" 11 10 b f f 20 23 16 36 416 475 102 106 )
+insert ( 418 "<" 11 10 b f f 20 23 16 76 430 476 103 107 )
+insert ( 419 ">" 11 10 b f f 20 23 16 37 420 477 104 108 )
+insert ( 420 "<=" 11 10 b f f 20 23 16 82 419 478 336 386 )
+insert ( 430 ">=" 11 10 b f f 20 23 16 80 418 479 337 398 )
+insert ( 439 "%" 11 10 b f f 20 20 20 0 0 945 - - )
+insert ( 473 "@" 11 10 l f f 0 20 20 0 0 1230 - - )
+insert ( 484 - 11 10 l f f 0 20 20 0 0 462 - - )
+insert ( 485 "<<" 11 10 b f f 604 604 16 0 0 341 1300 1301 )
+insert ( 486 "&<" 11 10 b f f 604 604 16 0 0 342 1300 1301 )
+insert ( 487 "&>" 11 10 b f f 604 604 16 0 0 343 1300 1301 )
+insert ( 488 ">>" 11 10 b f f 604 604 16 0 0 344 1300 1301 )
+insert ( 489 "<@" 11 10 b f f 604 604 16 490 0 345 1302 1303 )
+insert ( 490 "@>" 11 10 b f f 604 604 16 489 0 340 1302 1303 )
+insert ( 491 "~=" 11 10 b f f 604 604 16 491 0 339 101 105 )
+insert ( 492 "&&" 11 10 b f f 604 604 16 492 0 346 139 140 )
+insert ( 493 "<<" 11 10 b f f 603 603 16 0 0 188 1300 1301 )
+insert ( 494 "&<" 11 10 b f f 603 603 16 0 0 189 1300 1301 )
+insert ( 495 "&>" 11 10 b f f 603 603 16 0 0 190 1300 1301 )
+insert ( 496 ">>" 11 10 b f f 603 603 16 0 0 191 1300 1301 )
+insert ( 497 "<@" 11 10 b f f 603 603 16 498 0 192 1302 1303 )
+insert ( 498 "@>" 11 10 b f f 603 603 16 497 0 187 1302 1303 )
+insert ( 499 "~=" 11 10 b f f 603 603 16 499 0 186 101 105 )
+insert ( 500 "&&" 11 10 b f f 603 603 16 500 0 125 139 140 )
+insert ( 501 ">=" 11 10 b f f 603 603 16 505 504 126 139 140 )
+insert ( 502 ">" 11 10 b f f 603 603 16 504 505 127 139 140 )
+insert ( 503 "=" 11 10 b f f 603 603 16 503 0 128 101 105 )
+insert ( 504 "<" 11 10 b f f 603 603 16 502 501 129 139 140 )
+insert ( 505 "<=" 11 10 b f f 603 603 16 501 502 130 139 140 )
+insert ( 506 ">^" 11 10 b f f 600 600 16 0 0 131 1300 1301 )
+insert ( 507 "<<" 11 10 b f f 600 600 16 0 0 132 1300 1301 )
+insert ( 508 ">>" 11 10 b f f 600 600 16 0 0 133 1300 1301 )
+insert ( 509 "<^" 11 10 b f f 600 600 16 0 0 134 1300 1301 )
+insert ( 510 "~=" 11 10 b f f 600 600 16 510 713 135 101 105 )
+insert ( 511 "<@" 11 10 b f f 600 603 16 433 0 136 1302 1303 )
+insert ( 433 "@>" 11 10 b f f 603 600 16 511 0 193 1302 1303 )
+insert ( 512 "<@" 11 10 b f f 600 602 16 755 0 137 - - )
+insert ( 513 "@@" 11 10 l f f 0 603 600 0 0 138 - - )
+insert ( 514 "*" 11 10 b f f 23 23 23 514 0 141 - - )
+insert ( 517 "<->" 11 10 b f f 600 600 701 517 0 991 - - )
+insert ( 518 "<>" 11 10 b f f 23 23 16 518 96 144 102 106 )
+insert ( 519 "<>" 11 10 b f f 21 21 16 519 94 145 102 106 )
+insert ( 520 ">" 11 10 b f f 21 21 16 95 522 146 104 108 )
+insert ( 521 ">" 11 10 b f f 23 23 16 97 523 147 104 108 )
+insert ( 522 "<=" 11 10 b f f 21 21 16 524 520 148 336 386 )
+insert ( 523 "<=" 11 10 b f f 23 23 16 525 521 149 336 386 )
+insert ( 524 ">=" 11 10 b f f 21 21 16 522 95 151 337 398 )
+insert ( 525 ">=" 11 10 b f f 23 23 16 523 97 150 337 398 )
+insert ( 526 "*" 11 10 b f f 21 21 21 526 0 152 - - )
+insert ( 527 "/" 11 10 b f f 21 21 21 0 0 153 - - )
+insert ( 528 "/" 11 10 b f f 23 23 23 0 0 154 - - )
+insert ( 529 "%" 11 10 b f f 21 21 21 0 0 155 - - )
+insert ( 530 "%" 11 10 b f f 23 23 23 0 0 156 - - )
+insert ( 531 "<>" 11 10 b f f 25 25 16 531 98 157 102 106 )
+insert ( 532 "=" 11 10 b t t 21 23 16 533 538 158 101 105 )
+insert ( 533 "=" 11 10 b t t 23 21 16 532 539 159 101 105 )
+insert ( 534 "<" 11 10 b f f 21 23 16 537 542 160 103 107 )
+insert ( 535 "<" 11 10 b f f 23 21 16 536 543 161 103 107 )
+insert ( 536 ">" 11 10 b f f 21 23 16 535 540 162 104 108 )
+insert ( 537 ">" 11 10 b f f 23 21 16 534 541 163 104 108 )
+insert ( 538 "<>" 11 10 b f f 21 23 16 539 532 164 102 106 )
+insert ( 539 "<>" 11 10 b f f 23 21 16 538 533 165 102 106 )
+insert ( 540 "<=" 11 10 b f f 21 23 16 543 536 166 336 386 )
+insert ( 541 "<=" 11 10 b f f 23 21 16 542 537 167 336 386 )
+insert ( 542 ">=" 11 10 b f f 21 23 16 541 534 168 337 398 )
+insert ( 543 ">=" 11 10 b f f 23 21 16 540 535 169 337 398 )
+insert ( 544 "*" 11 10 b f f 21 23 23 545 0 170 - - )
+insert ( 545 "*" 11 10 b f f 23 21 23 544 0 171 - - )
+insert ( 546 "/" 11 10 b f f 21 23 23 0 0 172 - - )
+insert ( 547 "/" 11 10 b f f 23 21 23 0 0 173 - - )
+insert ( 550 "+" 11 10 b f f 21 21 21 550 0 176 - - )
+insert ( 551 "+" 11 10 b f f 23 23 23 551 0 177 - - )
+insert ( 552 "+" 11 10 b f f 21 23 23 553 0 178 - - )
+insert ( 553 "+" 11 10 b f f 23 21 23 552 0 179 - - )
+insert ( 554 - 11 10 b f f 21 21 21 0 0 180 - - )
+insert ( 555 - 11 10 b f f 23 23 23 0 0 181 - - )
+insert ( 556 - 11 10 b f f 21 23 23 0 0 182 - - )
+insert ( 557 - 11 10 b f f 23 21 23 0 0 183 - - )
+insert ( 558 - 11 10 l f f 0 23 23 0 0 212 - - )
+insert ( 559 - 11 10 l f f 0 21 21 0 0 213 - - )
+insert ( 584 - 11 10 l f f 0 700 700 0 0 206 - - )
+insert ( 585 - 11 10 l f f 0 701 701 0 0 220 - - )
+insert ( 586 "+" 11 10 b f f 700 700 700 586 0 204 - - )
+insert ( 587 - 11 10 b f f 700 700 700 0 0 205 - - )
+insert ( 588 "/" 11 10 b f f 700 700 700 0 0 203 - - )
+insert ( 589 "*" 11 10 b f f 700 700 700 589 0 202 - - )
+insert ( 590 "@" 11 10 l f f 0 700 700 0 0 207 - - )
+insert ( 591 "+" 11 10 b f f 701 701 701 591 0 218 - - )
+insert ( 592 - 11 10 b f f 701 701 701 0 0 219 - - )
+insert ( 593 "/" 11 10 b f f 701 701 701 0 0 217 - - )
+insert ( 594 "*" 11 10 b f f 701 701 701 594 0 216 - - )
+insert ( 595 "@" 11 10 l f f 0 701 701 0 0 221 - - )
+insert ( 596 "|/" 11 10 l f f 0 701 701 0 0 230 - - )
+insert ( 597 "||/" 11 10 l f f 0 701 701 0 0 231 - - )
+insert ( 607 "=" 11 10 b t t 26 26 16 607 608 184 101 105 )
+insert ( 608 "<>" 11 10 b f f 26 26 16 608 607 185 102 106 )
+insert ( 609 "<" 11 10 b f f 26 26 16 610 612 716 103 107 )
+insert ( 610 ">" 11 10 b f f 26 26 16 609 611 1638 104 108 )
+insert ( 611 "<=" 11 10 b f f 26 26 16 612 610 717 336 386 )
+insert ( 612 ">=" 11 10 b f f 26 26 16 611 609 1639 337 398 )
+insert ( 644 "<>" 11 10 b f f 30 30 16 644 649 619 102 106 )
+insert ( 645 "<" 11 10 b f f 30 30 16 646 648 677 103 107 )
+insert ( 646 ">" 11 10 b f f 30 30 16 645 647 681 104 108 )
+insert ( 647 "<=" 11 10 b f f 30 30 16 648 646 678 336 386 )
+insert ( 648 ">=" 11 10 b f f 30 30 16 647 645 680 337 398 )
+insert ( 649 "=" 11 10 b t t 30 30 16 649 644 679 101 105 )
+insert ( 613 "<->" 11 10 b f f 600 628 701 760 0 725 - - )
+insert ( 760 "<->" 11 10 b f f 628 600 701 613 0 702 - - )
+insert ( 614 "<->" 11 10 b f f 600 601 701 761 0 363 - - )
+insert ( 761 "<->" 11 10 b f f 601 600 701 614 0 380 - - )
+insert ( 615 "<->" 11 10 b f f 600 603 701 606 0 364 - - )
+insert ( 606 "<->" 11 10 b f f 603 600 701 615 0 357 - - )
+insert ( 616 "<->" 11 10 b f f 601 628 701 762 0 727 - - )
+insert ( 762 "<->" 11 10 b f f 628 601 701 616 0 704 - - )
+insert ( 617 "<->" 11 10 b f f 601 603 701 763 0 365 - - )
+insert ( 763 "<->" 11 10 b f f 603 601 701 617 0 381 - - )
+insert ( 618 "<->" 11 10 b f f 600 602 701 784 0 371 - - )
+insert ( 784 "<->" 11 10 b f f 602 600 701 618 0 421 - - )
+insert ( 620 "=" 11 10 b t t 700 700 16 620 621 287 101 105 )
+insert ( 621 "<>" 11 10 b f f 700 700 16 621 620 288 102 106 )
+insert ( 622 "<" 11 10 b f f 700 700 16 623 625 289 103 107 )
+insert ( 623 ">" 11 10 b f f 700 700 16 622 624 291 104 108 )
+insert ( 624 "<=" 11 10 b f f 700 700 16 625 623 290 336 386 )
+insert ( 625 ">=" 11 10 b f f 700 700 16 624 622 292 337 398 )
+insert ( 630 "<>" 11 10 b f f 18 18 16 630 92 70 102 106 )
+insert ( 631 "<" 11 10 b f f 18 18 16 633 634 1246 103 107 )
+insert ( 632 "<=" 11 10 b f f 18 18 16 634 633 72 336 386 )
+insert ( 633 ">" 11 10 b f f 18 18 16 631 632 73 104 108 )
+insert ( 634 ">=" 11 10 b f f 18 18 16 632 631 74 337 398 )
+insert ( 639 "~" 11 10 b f f 19 25 16 0 640 79 1818 1824 )
+insert ( 640 "!~" 11 10 b f f 19 25 16 0 639 1252 1821 1827 )
+insert ( 641 "~" 11 10 b f f 25 25 16 0 642 1254 1818 1824 )
+insert ( 642 "!~" 11 10 b f f 25 25 16 0 641 1256 1821 1827 )
+insert ( 643 "<>" 11 10 b f f 19 19 16 643 93 659 102 106 )
+insert ( 654 "||" 11 10 b f f 25 25 25 0 0 1258 - - )
+insert ( 660 "<" 11 10 b f f 19 19 16 662 663 655 103 107 )
+insert ( 661 "<=" 11 10 b f f 19 19 16 663 662 656 336 386 )
+insert ( 662 ">" 11 10 b f f 19 19 16 660 661 657 104 108 )
+insert ( 663 ">=" 11 10 b f f 19 19 16 661 660 658 337 398 )
+insert ( 664 "<" 11 10 b f f 25 25 16 666 667 740 103 107 )
+insert ( 665 "<=" 11 10 b f f 25 25 16 667 666 741 336 386 )
+insert ( 666 ">" 11 10 b f f 25 25 16 664 665 742 104 108 )
+insert ( 667 ">=" 11 10 b f f 25 25 16 665 664 743 337 398 )
+insert ( 670 "=" 11 10 b t t 701 701 16 670 671 293 101 105 )
+insert ( 671 "<>" 11 10 b f f 701 701 16 671 670 294 102 106 )
+insert ( 672 "<" 11 10 b f f 701 701 16 674 675 295 103 107 )
+insert ( 673 "<=" 11 10 b f f 701 701 16 675 674 296 336 386 )
+insert ( 674 ">" 11 10 b f f 701 701 16 672 673 297 104 108 )
+insert ( 675 ">=" 11 10 b f f 701 701 16 673 672 298 337 398 )
+insert ( 682 "@" 11 10 l f f 0 21 21 0 0 1253 - - )
+insert ( 684 "+" 11 10 b f f 20 20 20 684 0 463 - - )
+insert ( 685 - 11 10 b f f 20 20 20 0 0 464 - - )
+insert ( 686 "*" 11 10 b f f 20 20 20 686 0 465 - - )
+insert ( 687 "/" 11 10 b f f 20 20 20 0 0 466 - - )
+insert ( 688 "+" 11 10 b f f 20 23 20 692 0 1274 - - )
+insert ( 689 - 11 10 b f f 20 23 20 0 0 1275 - - )
+insert ( 690 "*" 11 10 b f f 20 23 20 694 0 1276 - - )
+insert ( 691 "/" 11 10 b f f 20 23 20 0 0 1277 - - )
+insert ( 692 "+" 11 10 b f f 23 20 20 688 0 1278 - - )
+insert ( 693 - 11 10 b f f 23 20 20 0 0 1279 - - )
+insert ( 694 "*" 11 10 b f f 23 20 20 690 0 1280 - - )
+insert ( 695 "/" 11 10 b f f 23 20 20 0 0 1281 - - )
+insert ( 818 "+" 11 10 b f f 20 21 20 822 0 837 - - )
+insert ( 819 - 11 10 b f f 20 21 20 0 0 838 - - )
+insert ( 820 "*" 11 10 b f f 20 21 20 824 0 839 - - )
+insert ( 821 "/" 11 10 b f f 20 21 20 0 0 840 - - )
+insert ( 822 "+" 11 10 b f f 21 20 20 818 0 841 - - )
+insert ( 823 - 11 10 b f f 21 20 20 0 0 942 - - )
+insert ( 824 "*" 11 10 b f f 21 20 20 820 0 943 - - )
+insert ( 825 "/" 11 10 b f f 21 20 20 0 0 948 - - )
+insert ( 706 "<->" 11 10 b f f 603 603 701 706 0 978 - - )
+insert ( 707 "<->" 11 10 b f f 602 602 701 707 0 370 - - )
+insert ( 708 "<->" 11 10 b f f 628 628 701 708 0 239 - - )
+insert ( 709 "<->" 11 10 b f f 601 601 701 709 0 361 - - )
+insert ( 712 "<->" 11 10 b f f 604 604 701 712 0 729 - - )
+insert ( 713 "<>" 11 10 b f f 600 600 16 713 510 988 102 106 )
+insert ( 731 "+" 11 10 b f f 600 600 600 731 0 1441 - - )
+insert ( 732 - 11 10 b f f 600 600 600 0 0 1442 - - )
+insert ( 733 "*" 11 10 b f f 600 600 600 733 0 1443 - - )
+insert ( 734 "/" 11 10 b f f 600 600 600 0 0 1444 - - )
+insert ( 735 "+" 11 10 b f f 602 602 602 735 0 1435 - - )
+insert ( 736 "+" 11 10 b f f 602 600 602 0 0 1436 - - )
+insert ( 737 - 11 10 b f f 602 600 602 0 0 1437 - - )
+insert ( 738 "*" 11 10 b f f 602 600 602 0 0 1438 - - )
+insert ( 739 "/" 11 10 b f f 602 600 602 0 0 1439 - - )
+insert ( 755 "@>" 11 10 b f f 602 600 16 512 0 1426 - - )
+insert ( 756 "<@" 11 10 b f f 600 604 16 757 0 1429 1302 1303 )
+insert ( 757 "@>" 11 10 b f f 604 600 16 756 0 1428 1302 1303 )
+insert ( 758 "<@" 11 10 b f f 600 718 16 759 0 1478 1302 1303 )
+insert ( 759 "@>" 11 10 b f f 718 600 16 758 0 1477 1302 1303 )
+insert ( 773 "@" 11 10 l f f 0 23 23 0 0 1251 - - )
+insert ( 792 "=" 11 10 b f f 602 602 16 792 0 984 101 105 )
+insert ( 793 "<" 11 10 b f f 602 602 16 794 0 982 - - )
+insert ( 794 ">" 11 10 b f f 602 602 16 793 0 983 - - )
+insert ( 795 "<=" 11 10 b f f 602 602 16 796 0 985 - - )
+insert ( 796 ">=" 11 10 b f f 602 602 16 795 0 986 - - )
+insert ( 797 "#" 11 10 l f f 0 602 23 0 0 1432 - - )
+insert ( 798 "?#" 11 10 b f f 602 602 16 0 0 973 - - )
+insert ( 799 "@-@" 11 10 l f f 0 602 701 0 0 987 - - )
+insert ( 800 ">^" 11 10 b f f 603 603 16 0 0 115 1300 1301 )
+insert ( 801 "<^" 11 10 b f f 603 603 16 0 0 116 1300 1301 )
+insert ( 802 "?#" 11 10 b f f 603 603 16 0 0 125 139 140 )
+insert ( 803 "#" 11 10 b f f 603 603 603 0 0 980 - - )
+insert ( 804 "+" 11 10 b f f 603 600 603 0 0 1422 - - )
+insert ( 805 - 11 10 b f f 603 600 603 0 0 1423 - - )
+insert ( 806 "*" 11 10 b f f 603 600 603 0 0 1424 - - )
+insert ( 807 "/" 11 10 b f f 603 600 603 0 0 1425 - - )
+insert ( 808 "?-" 11 10 b f f 600 600 16 808 0 990 - - )
+insert ( 809 "?|" 11 10 b f f 600 600 16 809 0 989 - - )
+insert ( 843 "*" 11 10 b f f 790 700 790 845 0 846 - - )
+insert ( 844 "/" 11 10 b f f 790 700 790 0 0 847 - - )
+insert ( 845 "*" 11 10 b f f 700 790 790 843 0 848 - - )
+insert ( 900 "=" 11 10 b t f 790 790 16 900 901 888 101 105 )
+insert ( 901 "<>" 11 10 b f f 790 790 16 901 900 889 102 106 )
+insert ( 902 "<" 11 10 b f f 790 790 16 903 905 890 103 107 )
+insert ( 903 ">" 11 10 b f f 790 790 16 902 904 892 104 108 )
+insert ( 904 "<=" 11 10 b f f 790 790 16 905 903 891 336 386 )
+insert ( 905 ">=" 11 10 b f f 790 790 16 904 902 893 337 398 )
+insert ( 906 "+" 11 10 b f f 790 790 790 906 0 894 - - )
+insert ( 907 - 11 10 b f f 790 790 790 0 0 895 - - )
+insert ( 908 "*" 11 10 b f f 790 701 790 916 0 896 - - )
+insert ( 909 "/" 11 10 b f f 790 701 790 0 0 897 - - )
+insert ( 3346 "*" 11 10 b f f 790 20 790 3349 0 3344 - - )
+insert ( 3347 "/" 11 10 b f f 790 20 790 0 0 3345 - - )
+insert ( 912 "*" 11 10 b f f 790 23 790 917 0 864 - - )
+insert ( 913 "/" 11 10 b f f 790 23 790 0 0 865 - - )
+insert ( 914 "*" 11 10 b f f 790 21 790 918 0 866 - - )
+insert ( 915 "/" 11 10 b f f 790 21 790 0 0 867 - - )
+insert ( 916 "*" 11 10 b f f 701 790 790 908 0 919 - - )
+insert ( 3349 "*" 11 10 b f f 20 790 790 3346 0 3399 - - )
+insert ( 917 "*" 11 10 b f f 23 790 790 912 0 862 - - )
+insert ( 918 "*" 11 10 b f f 21 790 790 914 0 863 - - )
+insert ( 3825 "/" 11 10 b f f 790 790 701 0 0 3822 - - )
+insert ( 965 "^" 11 10 b f f 701 701 701 0 0 232 - - )
+insert ( 966 "+" 11 10 b f f 1034 1033 1034 0 0 1035 - - )
+insert ( 967 - 11 10 b f f 1034 1033 1034 0 0 1036 - - )
+insert ( 968 "@>" 11 10 b f f 1034 1033 16 0 0 1037 - - )
+insert ( 974 "=" 11 10 b f t 1033 1033 16 974 0 1062 101 105 )
+insert ( 969 "@@" 11 10 l f f 0 601 600 0 0 225 - - )
+insert ( 970 "@@" 11 10 l f f 0 602 600 0 0 226 - - )
+insert ( 971 "@@" 11 10 l f f 0 604 600 0 0 227 - - )
+insert ( 1054 "=" 11 10 b t t 1042 1042 16 1054 1057 1048 101 105 )
+insert ( 1055 "~" 11 10 b f f 1042 25 16 0 1056 1658 1818 1824 )
+insert ( 1056 "!~" 11 10 b f f 1042 25 16 0 1055 1659 1821 1827 )
+insert ( 1057 "<>" 11 10 b f f 1042 1042 16 1057 1054 1053 102 106 )
+insert ( 1058 "<" 11 10 b f f 1042 1042 16 1060 1061 1049 103 107 )
+insert ( 1059 "<=" 11 10 b f f 1042 1042 16 1061 1060 1050 336 386 )
+insert ( 1060 ">" 11 10 b f f 1042 1042 16 1058 1059 1051 104 108 )
+insert ( 1061 ">=" 11 10 b f f 1042 1042 16 1059 1058 1052 337 398 )
+insert ( 1070 "=" 11 10 b t t 2277 2277 16 1070 1071 744 101 105 )
+insert ( 1071 "<>" 11 10 b f f 2277 2277 16 1071 1070 390 102 106 )
+insert ( 1072 "<" 11 10 b f f 2277 2277 16 1073 1075 391 103 107 )
+insert ( 1073 ">" 11 10 b f f 2277 2277 16 1072 1074 392 104 108 )
+insert ( 1074 "<=" 11 10 b f f 2277 2277 16 1075 1073 393 336 386 )
+insert ( 1075 ">=" 11 10 b f f 2277 2277 16 1074 1072 396 337 398 )
+insert ( 1076 "+" 11 10 b f f 1082 1186 1114 2551 0 2071 - - )
+insert ( 1077 - 11 10 b f f 1082 1186 1114 0 0 2072 - - )
+insert ( 1093 "=" 11 10 b t t 1082 1082 16 1093 1094 1086 101 105 )
+insert ( 1094 "<>" 11 10 b f f 1082 1082 16 1094 1093 1091 102 106 )
+insert ( 1095 "<" 11 10 b f f 1082 1082 16 1097 1098 1087 103 107 )
+insert ( 1096 "<=" 11 10 b f f 1082 1082 16 1098 1097 1088 336 386 )
+insert ( 1097 ">" 11 10 b f f 1082 1082 16 1095 1096 1089 104 108 )
+insert ( 1098 ">=" 11 10 b f f 1082 1082 16 1096 1095 1090 337 398 )
+insert ( 1099 - 11 10 b f f 1082 1082 23 0 0 1140 - - )
+insert ( 1100 "+" 11 10 b f f 1082 23 1082 2555 0 1141 - - )
+insert ( 1101 - 11 10 b f f 1082 23 1082 0 0 1142 - - )
+insert ( 1108 "=" 11 10 b t t 1083 1083 16 1108 1109 1145 101 105 )
+insert ( 1109 "<>" 11 10 b f f 1083 1083 16 1109 1108 1106 102 106 )
+insert ( 1110 "<" 11 10 b f f 1083 1083 16 1112 1113 1102 103 107 )
+insert ( 1111 "<=" 11 10 b f f 1083 1083 16 1113 1112 1103 336 386 )
+insert ( 1112 ">" 11 10 b f f 1083 1083 16 1110 1111 1104 104 108 )
+insert ( 1113 ">=" 11 10 b f f 1083 1083 16 1111 1110 1105 337 398 )
+insert ( 1550 "=" 11 10 b t t 1266 1266 16 1550 1551 1352 101 105 )
+insert ( 1551 "<>" 11 10 b f f 1266 1266 16 1551 1550 1353 102 106 )
+insert ( 1552 "<" 11 10 b f f 1266 1266 16 1554 1555 1354 103 107 )
+insert ( 1553 "<=" 11 10 b f f 1266 1266 16 1555 1554 1355 336 386 )
+insert ( 1554 ">" 11 10 b f f 1266 1266 16 1552 1553 1357 104 108 )
+insert ( 1555 ">=" 11 10 b f f 1266 1266 16 1553 1552 1356 337 398 )
+insert ( 1116 "+" 11 10 b f f 700 701 701 1126 0 281 - - )
+insert ( 1117 - 11 10 b f f 700 701 701 0 0 282 - - )
+insert ( 1118 "/" 11 10 b f f 700 701 701 0 0 280 - - )
+insert ( 1119 "*" 11 10 b f f 700 701 701 1129 0 279 - - )
+insert ( 1120 "=" 11 10 b t t 700 701 16 1130 1121 299 101 105 )
+insert ( 1121 "<>" 11 10 b f f 700 701 16 1131 1120 300 102 106 )
+insert ( 1122 "<" 11 10 b f f 700 701 16 1133 1125 301 103 107 )
+insert ( 1123 ">" 11 10 b f f 700 701 16 1132 1124 303 104 108 )
+insert ( 1124 "<=" 11 10 b f f 700 701 16 1135 1123 302 336 386 )
+insert ( 1125 ">=" 11 10 b f f 700 701 16 1134 1122 304 337 398 )
+insert ( 1126 "+" 11 10 b f f 701 700 701 1116 0 285 - - )
+insert ( 1127 - 11 10 b f f 701 700 701 0 0 286 - - )
+insert ( 1128 "/" 11 10 b f f 701 700 701 0 0 284 - - )
+insert ( 1129 "*" 11 10 b f f 701 700 701 1119 0 283 - - )
+insert ( 1130 "=" 11 10 b t t 701 700 16 1120 1131 305 101 105 )
+insert ( 1131 "<>" 11 10 b f f 701 700 16 1121 1130 306 102 106 )
+insert ( 1132 "<" 11 10 b f f 701 700 16 1123 1135 307 103 107 )
+insert ( 1133 ">" 11 10 b f f 701 700 16 1122 1134 309 104 108 )
+insert ( 1134 "<=" 11 10 b f f 701 700 16 1125 1133 308 336 386 )
+insert ( 1135 ">=" 11 10 b f f 701 700 16 1124 1132 310 337 398 )
+insert ( 1207 "~~" 11 10 b f f 19 25 16 0 1208 858 1819 1825 )
+insert ( 1208 "!~~" 11 10 b f f 19 25 16 0 1207 859 1822 1828 )
+insert ( 1209 "~~" 11 10 b f f 25 25 16 0 1210 850 1819 1825 )
+insert ( 1210 "!~~" 11 10 b f f 25 25 16 0 1209 851 1822 1828 )
+insert ( 1211 "~~" 11 10 b f f 1042 25 16 0 1212 1631 1819 1825 )
+insert ( 1212 "!~~" 11 10 b f f 1042 25 16 0 1211 1632 1822 1828 )
+insert ( 1226 "~*" 11 10 b f f 19 25 16 0 1227 1240 1820 1826 )
+insert ( 1227 "!~*" 11 10 b f f 19 25 16 0 1226 1241 1823 1829 )
+insert ( 1228 "~*" 11 10 b f f 25 25 16 0 1229 1238 1820 1826 )
+insert ( 1229 "!~*" 11 10 b f f 25 25 16 0 1228 1239 1823 1829 )
+insert ( 1234 "~*" 11 10 b f f 1042 25 16 0 1235 1656 1820 1826 )
+insert ( 1235 "!~*" 11 10 b f f 1042 25 16 0 1234 1657 1823 1829 )
+insert ( 1320 "=" 11 10 b t t 1184 1184 16 1320 1321 1152 101 105 )
+insert ( 1321 "<>" 11 10 b f f 1184 1184 16 1321 1320 1153 102 106 )
+insert ( 1322 "<" 11 10 b f f 1184 1184 16 1324 1325 1154 103 107 )
+insert ( 1323 "<=" 11 10 b f f 1184 1184 16 1325 1324 1155 336 386 )
+insert ( 1324 ">" 11 10 b f f 1184 1184 16 1322 1323 1157 104 108 )
+insert ( 1325 ">=" 11 10 b f f 1184 1184 16 1323 1322 1156 337 398 )
+insert ( 1327 "+" 11 10 b f f 1184 1186 1184 2554 0 1189 - - )
+insert ( 1328 - 11 10 b f f 1184 1184 1186 0 0 1188 - - )
+insert ( 1329 - 11 10 b f f 1184 1186 1184 0 0 1190 - - )
+insert ( 1330 "=" 11 10 b t t 1186 1186 16 1330 1331 1162 101 105 )
+insert ( 1331 "<>" 11 10 b f f 1186 1186 16 1331 1330 1163 102 106 )
+insert ( 1332 "<" 11 10 b f f 1186 1186 16 1334 1335 1164 103 107 )
+insert ( 1333 "<=" 11 10 b f f 1186 1186 16 1335 1334 1165 336 386 )
+insert ( 1334 ">" 11 10 b f f 1186 1186 16 1332 1333 1167 104 108 )
+insert ( 1335 ">=" 11 10 b f f 1186 1186 16 1333 1332 1166 337 398 )
+insert ( 1336 - 11 10 l f f 0 1186 1186 0 0 1168 - - )
+insert ( 1337 "+" 11 10 b f f 1186 1186 1186 1337 0 1169 - - )
+insert ( 1338 - 11 10 b f f 1186 1186 1186 0 0 1170 - - )
+insert ( 1360 "+" 11 10 b f f 1082 1083 1114 1363 0 1272 - - )
+insert ( 1361 "+" 11 10 b f f 1082 1266 1184 1366 0 1297 - - )
+insert ( 1363 "+" 11 10 b f f 1083 1082 1114 1360 0 1296 - - )
+insert ( 1366 "+" 11 10 b f f 1266 1082 1184 1361 0 1298 - - )
+insert ( 1399 - 11 10 b f f 1083 1083 1186 0 0 1690 - - )
+insert ( 1420 "@@" 11 10 l f f 0 718 600 0 0 1472 - - )
+insert ( 1500 "=" 11 10 b f f 718 718 16 1500 1501 1462 101 105 )
+insert ( 1501 "<>" 11 10 b f f 718 718 16 1501 1500 1463 102 106 )
+insert ( 1502 "<" 11 10 b f f 718 718 16 1503 1505 1464 139 140 )
+insert ( 1503 ">" 11 10 b f f 718 718 16 1502 1504 1465 139 140 )
+insert ( 1504 "<=" 11 10 b f f 718 718 16 1505 1503 1466 139 140 )
+insert ( 1505 ">=" 11 10 b f f 718 718 16 1504 1502 1467 139 140 )
+insert ( 1506 "<<" 11 10 b f f 718 718 16 0 0 1454 1300 1301 )
+insert ( 1507 "&<" 11 10 b f f 718 718 16 0 0 1455 1300 1301 )
+insert ( 1508 "&>" 11 10 b f f 718 718 16 0 0 1456 1300 1301 )
+insert ( 1509 ">>" 11 10 b f f 718 718 16 0 0 1457 1300 1301 )
+insert ( 1510 "<@" 11 10 b f f 718 718 16 1511 0 1458 1302 1303 )
+insert ( 1511 "@>" 11 10 b f f 718 718 16 1510 0 1453 1302 1303 )
+insert ( 1512 "~=" 11 10 b f f 718 718 16 1512 0 1452 101 105 )
+insert ( 1513 "&&" 11 10 b f f 718 718 16 1513 0 1459 139 140 )
+insert ( 1514 "|>>" 11 10 b f f 718 718 16 0 0 1461 1300 1301 )
+insert ( 1515 "<<|" 11 10 b f f 718 718 16 0 0 1460 1300 1301 )
+insert ( 1516 "+" 11 10 b f f 718 600 718 0 0 1146 - - )
+insert ( 1517 - 11 10 b f f 718 600 718 0 0 1147 - - )
+insert ( 1518 "*" 11 10 b f f 718 600 718 0 0 1148 - - )
+insert ( 1519 "/" 11 10 b f f 718 600 718 0 0 1149 - - )
+insert ( 1520 "<->" 11 10 b f f 718 718 701 1520 0 1471 - - )
+insert ( 1521 "#" 11 10 l f f 0 604 23 0 0 1445 - - )
+insert ( 1522 "<->" 11 10 b f f 600 718 701 3291 0 1476 - - )
+insert ( 3291 "<->" 11 10 b f f 718 600 701 1522 0 3290 - - )
+insert ( 3276 "<->" 11 10 b f f 600 604 701 3289 0 3275 - - )
+insert ( 3289 "<->" 11 10 b f f 604 600 701 3276 0 3292 - - )
+insert ( 1523 "<->" 11 10 b f f 718 604 701 1383 0 728 - - )
+insert ( 1383 "<->" 11 10 b f f 604 718 701 1523 0 785 - - )
+insert ( 1524 "<->" 11 10 b f f 628 603 701 1382 0 726 - - )
+insert ( 1382 "<->" 11 10 b f f 603 628 701 1524 0 703 - - )
+insert ( 1525 "?#" 11 10 b f f 601 601 16 1525 0 994 - - )
+insert ( 1526 "?||" 11 10 b f f 601 601 16 1526 0 995 - - )
+insert ( 1527 "?-|" 11 10 b f f 601 601 16 1527 0 996 - - )
+insert ( 1528 "?-" 11 10 l f f 0 601 16 0 0 998 - - )
+insert ( 1529 "?|" 11 10 l f f 0 601 16 0 0 997 - - )
+insert ( 1535 "=" 11 10 b f f 601 601 16 1535 1586 999 101 105 )
+insert ( 1536 "#" 11 10 b f f 601 601 600 1536 0 362 - - )
+insert ( 1537 "?#" 11 10 b f f 601 628 16 0 0 277 - - )
+insert ( 1538 "?#" 11 10 b f f 601 603 16 0 0 373 - - )
+insert ( 1539 "?#" 11 10 b f f 628 603 16 0 0 278 - - )
+insert ( 1546 "<@" 11 10 b f f 600 628 16 0 0 959 - - )
+insert ( 1547 "<@" 11 10 b f f 600 601 16 0 0 369 - - )
+insert ( 1548 "<@" 11 10 b f f 601 628 16 0 0 960 - - )
+insert ( 1549 "<@" 11 10 b f f 601 603 16 0 0 372 - - )
+insert ( 1557 "##" 11 10 b f f 600 628 600 0 0 961 - - )
+insert ( 1558 "##" 11 10 b f f 600 601 600 0 0 366 - - )
+insert ( 1559 "##" 11 10 b f f 600 603 600 0 0 367 - - )
+insert ( 1566 "##" 11 10 b f f 601 628 600 0 0 962 - - )
+insert ( 1567 "##" 11 10 b f f 601 603 600 0 0 368 - - )
+insert ( 1568 "##" 11 10 b f f 628 603 600 0 0 963 - - )
+insert ( 1577 "##" 11 10 b f f 628 601 600 0 0 1488 - - )
+insert ( 1578 "##" 11 10 b f f 601 601 600 0 0 1489 - - )
+insert ( 1583 "*" 11 10 b f f 1186 701 1186 1584 0 1618 - - )
+insert ( 1584 "*" 11 10 b f f 701 1186 1186 1583 0 1624 - - )
+insert ( 1585 "/" 11 10 b f f 1186 701 1186 0 0 1326 - - )
+insert ( 1586 "<>" 11 10 b f f 601 601 16 1586 1535 1482 102 106 )
+insert ( 1587 "<" 11 10 b f f 601 601 16 1589 1590 1483 - - )
+insert ( 1588 "<=" 11 10 b f f 601 601 16 1590 1589 1484 - - )
+insert ( 1589 ">" 11 10 b f f 601 601 16 1587 1588 1485 - - )
+insert ( 1590 ">=" 11 10 b f f 601 601 16 1588 1587 1486 - - )
+insert ( 1591 "@-@" 11 10 l f f 0 601 701 0 0 1487 - - )
+insert ( 1611 "?#" 11 10 b f f 628 628 16 1611 0 1495 - - )
+insert ( 1612 "?||" 11 10 b f f 628 628 16 1612 0 1496 - - )
+insert ( 1613 "?-|" 11 10 b f f 628 628 16 1613 0 1497 - - )
+insert ( 1614 "?-" 11 10 l f f 0 628 16 0 0 1499 - - )
+insert ( 1615 "?|" 11 10 l f f 0 628 16 0 0 1498 - - )
+insert ( 1616 "=" 11 10 b f f 628 628 16 1616 0 1492 101 105 )
+insert ( 1617 "#" 11 10 b f f 628 628 600 1617 0 1494 - - )
+insert ( 1220 "=" 11 10 b t t 829 829 16 1220 1221 830 101 105 )
+insert ( 1221 "<>" 11 10 b f f 829 829 16 1221 1220 835 102 106 )
+insert ( 1222 "<" 11 10 b f f 829 829 16 1224 1225 831 103 107 )
+insert ( 1223 "<=" 11 10 b f f 829 829 16 1225 1224 832 336 386 )
+insert ( 1224 ">" 11 10 b f f 829 829 16 1222 1223 833 104 108 )
+insert ( 1225 ">=" 11 10 b f f 829 829 16 1223 1222 834 337 398 )
+insert ( 3147 "~" 11 10 l f f 0 829 829 0 0 3144 - - )
+insert ( 3148 "&" 11 10 b f f 829 829 829 0 0 3145 - - )
+insert ( 3149 "|" 11 10 b f f 829 829 829 0 0 3146 - - )
+insert ( 3362 "=" 11 10 b t t 774 774 16 3362 3363 4113 101 105 )
+insert ( 3363 "<>" 11 10 b f f 774 774 16 3363 3362 4118 102 106 )
+insert ( 3364 "<" 11 10 b f f 774 774 16 3366 3367 4114 103 107 )
+insert ( 3365 "<=" 11 10 b f f 774 774 16 3367 3366 4115 336 386 )
+insert ( 3366 ">" 11 10 b f f 774 774 16 3364 3365 4116 104 108 )
+insert ( 3367 ">=" 11 10 b f f 774 774 16 3365 3364 4117 337 398 )
+insert ( 3368 "~" 11 10 l f f 0 774 774 0 0 4120 - - )
+insert ( 3369 "&" 11 10 b f f 774 774 774 0 0 4121 - - )
+insert ( 3370 "|" 11 10 b f f 774 774 774 0 0 4122 - - )
+insert ( 1201 "=" 11 10 b t t 869 869 16 1201 1202 920 101 105 )
+insert ( 1202 "<>" 11 10 b f f 869 869 16 1202 1201 925 102 106 )
+insert ( 1203 "<" 11 10 b f f 869 869 16 1205 1206 921 103 107 )
+insert ( 1204 "<=" 11 10 b f f 869 869 16 1206 1205 922 336 386 )
+insert ( 1205 ">" 11 10 b f f 869 869 16 1203 1204 923 104 108 )
+insert ( 1206 ">=" 11 10 b f f 869 869 16 1204 1203 924 337 398 )
+insert ( 931 "<<" 11 10 b f f 869 869 16 933 0 927 3560 3561 )
+insert ( 932 "<<=" 11 10 b f f 869 869 16 934 0 928 3560 3561 )
+insert ( 933 ">>" 11 10 b f f 869 869 16 931 0 929 3560 3561 )
+insert ( 934 ">>=" 11 10 b f f 869 869 16 932 0 930 3560 3561 )
+insert ( 3552 "&&" 11 10 b f f 869 869 16 3552 0 3551 3560 3561 )
+insert ( 2634 "~" 11 10 l f f 0 869 869 0 0 2627 - - )
+insert ( 2635 "&" 11 10 b f f 869 869 869 0 0 2628 - - )
+insert ( 2636 "|" 11 10 b f f 869 869 869 0 0 2629 - - )
+insert ( 2637 "+" 11 10 b f f 869 20 869 2638 0 2630 - - )
+insert ( 2638 "+" 11 10 b f f 20 869 869 2637 0 2631 - - )
+insert ( 2639 - 11 10 b f f 869 20 869 0 0 2632 - - )
+insert ( 2640 - 11 10 b f f 869 869 20 0 0 2633 - - )
+insert ( 1625 "~~*" 11 10 b f f 19 25 16 0 1626 1635 1814 1816 )
+insert ( 1626 "!~~*" 11 10 b f f 19 25 16 0 1625 1636 1815 1817 )
+insert ( 1627 "~~*" 11 10 b f f 25 25 16 0 1628 1633 1814 1816 )
+insert ( 1628 "!~~*" 11 10 b f f 25 25 16 0 1627 1634 1815 1817 )
+insert ( 1629 "~~*" 11 10 b f f 1042 25 16 0 1630 1660 1814 1816 )
+insert ( 1630 "!~~*" 11 10 b f f 1042 25 16 0 1629 1661 1815 1817 )
+insert ( 1751 - 11 10 l f f 0 1700 1700 0 0 1771 - - )
+insert ( 1752 "=" 11 10 b t t 1700 1700 16 1752 1753 1718 101 105 )
+insert ( 1753 "<>" 11 10 b f f 1700 1700 16 1753 1752 1719 102 106 )
+insert ( 1754 "<" 11 10 b f f 1700 1700 16 1756 1757 1722 103 107 )
+insert ( 1755 "<=" 11 10 b f f 1700 1700 16 1757 1756 1723 336 386 )
+insert ( 1756 ">" 11 10 b f f 1700 1700 16 1754 1755 1720 104 108 )
+insert ( 1757 ">=" 11 10 b f f 1700 1700 16 1755 1754 1721 337 398 )
+insert ( 1758 "+" 11 10 b f f 1700 1700 1700 1758 0 1724 - - )
+insert ( 1759 - 11 10 b f f 1700 1700 1700 0 0 1725 - - )
+insert ( 1760 "*" 11 10 b f f 1700 1700 1700 1760 0 1726 - - )
+insert ( 1761 "/" 11 10 b f f 1700 1700 1700 0 0 1727 - - )
+insert ( 1762 "%" 11 10 b f f 1700 1700 1700 0 0 1729 - - )
+insert ( 1038 "^" 11 10 b f f 1700 1700 1700 0 0 1739 - - )
+insert ( 1763 "@" 11 10 l f f 0 1700 1700 0 0 1704 - - )
+insert ( 1784 "=" 11 10 b t f 1560 1560 16 1784 1785 1581 101 105 )
+insert ( 1785 "<>" 11 10 b f f 1560 1560 16 1785 1784 1582 102 106 )
+insert ( 1786 "<" 11 10 b f f 1560 1560 16 1787 1789 1595 103 107 )
+insert ( 1787 ">" 11 10 b f f 1560 1560 16 1786 1788 1593 104 108 )
+insert ( 1788 "<=" 11 10 b f f 1560 1560 16 1789 1787 1594 336 386 )
+insert ( 1789 ">=" 11 10 b f f 1560 1560 16 1788 1786 1592 337 398 )
+insert ( 1791 "&" 11 10 b f f 1560 1560 1560 1791 0 1673 - - )
+insert ( 1792 "|" 11 10 b f f 1560 1560 1560 1792 0 1674 - - )
+insert ( 1793 "#" 11 10 b f f 1560 1560 1560 1793 0 1675 - - )
+insert ( 1794 "~" 11 10 l f f 0 1560 1560 0 0 1676 - - )
+insert ( 1795 "<<" 11 10 b f f 1560 23 1560 0 0 1677 - - )
+insert ( 1796 ">>" 11 10 b f f 1560 23 1560 0 0 1678 - - )
+insert ( 1797 "||" 11 10 b f f 1562 1562 1562 0 0 1679 - - )
+insert ( 1800 "+" 11 10 b f f 1083 1186 1083 1849 0 1747 - - )
+insert ( 1801 - 11 10 b f f 1083 1186 1083 0 0 1748 - - )
+insert ( 1802 "+" 11 10 b f f 1266 1186 1266 2552 0 1749 - - )
+insert ( 1803 - 11 10 b f f 1266 1186 1266 0 0 1750 - - )
+insert ( 1804 "=" 11 10 b t f 1562 1562 16 1804 1805 1666 101 105 )
+insert ( 1805 "<>" 11 10 b f f 1562 1562 16 1805 1804 1667 102 106 )
+insert ( 1806 "<" 11 10 b f f 1562 1562 16 1807 1809 1671 103 107 )
+insert ( 1807 ">" 11 10 b f f 1562 1562 16 1806 1808 1669 104 108 )
+insert ( 1808 "<=" 11 10 b f f 1562 1562 16 1809 1807 1670 336 386 )
+insert ( 1809 ">=" 11 10 b f f 1562 1562 16 1808 1806 1668 337 398 )
+insert ( 1849 "+" 11 10 b f f 1186 1083 1083 1800 0 1848 - - )
+insert ( 1862 "=" 11 10 b t t 21 20 16 1868 1863 1850 101 105 )
+insert ( 1863 "<>" 11 10 b f f 21 20 16 1869 1862 1851 102 106 )
+insert ( 1864 "<" 11 10 b f f 21 20 16 1871 1867 1852 103 107 )
+insert ( 1865 ">" 11 10 b f f 21 20 16 1870 1866 1853 104 108 )
+insert ( 1866 "<=" 11 10 b f f 21 20 16 1873 1865 1854 336 386 )
+insert ( 1867 ">=" 11 10 b f f 21 20 16 1872 1864 1855 337 398 )
+insert ( 1868 "=" 11 10 b t t 20 21 16 1862 1869 1856 101 105 )
+insert ( 1869 "<>" 11 10 b f f 20 21 16 1863 1868 1857 102 106 )
+insert ( 1870 "<" 11 10 b f f 20 21 16 1865 1873 1858 103 107 )
+insert ( 1871 ">" 11 10 b f f 20 21 16 1864 1872 1859 104 108 )
+insert ( 1872 "<=" 11 10 b f f 20 21 16 1867 1871 1860 336 386 )
+insert ( 1873 ">=" 11 10 b f f 20 21 16 1866 1870 1861 337 398 )
+insert ( 1874 "&" 11 10 b f f 21 21 21 1874 0 1892 - - )
+insert ( 1875 "|" 11 10 b f f 21 21 21 1875 0 1893 - - )
+insert ( 1876 "#" 11 10 b f f 21 21 21 1876 0 1894 - - )
+insert ( 1877 "~" 11 10 l f f 0 21 21 0 0 1895 - - )
+insert ( 1878 "<<" 11 10 b f f 21 23 21 0 0 1896 - - )
+insert ( 1879 ">>" 11 10 b f f 21 23 21 0 0 1897 - - )
+insert ( 1880 "&" 11 10 b f f 23 23 23 1880 0 1898 - - )
+insert ( 1881 "|" 11 10 b f f 23 23 23 1881 0 1899 - - )
+insert ( 1882 "#" 11 10 b f f 23 23 23 1882 0 1900 - - )
+insert ( 1883 "~" 11 10 l f f 0 23 23 0 0 1901 - - )
+insert ( 1884 "<<" 11 10 b f f 23 23 23 0 0 1902 - - )
+insert ( 1885 ">>" 11 10 b f f 23 23 23 0 0 1903 - - )
+insert ( 1886 "&" 11 10 b f f 20 20 20 1886 0 1904 - - )
+insert ( 1887 "|" 11 10 b f f 20 20 20 1887 0 1905 - - )
+insert ( 1888 "#" 11 10 b f f 20 20 20 1888 0 1906 - - )
+insert ( 1889 "~" 11 10 l f f 0 20 20 0 0 1907 - - )
+insert ( 1890 "<<" 11 10 b f f 20 23 20 0 0 1908 - - )
+insert ( 1891 ">>" 11 10 b f f 20 23 20 0 0 1909 - - )
+insert ( 1916 "+" 11 10 l f f 0 20 20 0 0 1910 - - )
+insert ( 1917 "+" 11 10 l f f 0 21 21 0 0 1911 - - )
+insert ( 1918 "+" 11 10 l f f 0 23 23 0 0 1912 - - )
+insert ( 1919 "+" 11 10 l f f 0 700 700 0 0 1913 - - )
+insert ( 1920 "+" 11 10 l f f 0 701 701 0 0 1914 - - )
+insert ( 1921 "+" 11 10 l f f 0 1700 1700 0 0 1915 - - )
+insert ( 1955 "=" 11 10 b t t 17 17 16 1955 1956 1948 101 105 )
+insert ( 1956 "<>" 11 10 b f f 17 17 16 1956 1955 1953 102 106 )
+insert ( 1957 "<" 11 10 b f f 17 17 16 1959 1960 1949 103 107 )
+insert ( 1958 "<=" 11 10 b f f 17 17 16 1960 1959 1950 336 386 )
+insert ( 1959 ">" 11 10 b f f 17 17 16 1957 1958 1951 104 108 )
+insert ( 1960 ">=" 11 10 b f f 17 17 16 1958 1957 1952 337 398 )
+insert ( 2016 "~~" 11 10 b f f 17 17 16 0 2017 2005 1819 1825 )
+insert ( 2017 "!~~" 11 10 b f f 17 17 16 0 2016 2006 1822 1828 )
+insert ( 2018 "||" 11 10 b f f 17 17 17 0 0 2011 - - )
+insert ( 2060 "=" 11 10 b t t 1114 1114 16 2060 2061 2052 101 105 )
+insert ( 2061 "<>" 11 10 b f f 1114 1114 16 2061 2060 2053 102 106 )
+insert ( 2062 "<" 11 10 b f f 1114 1114 16 2064 2065 2054 103 107 )
+insert ( 2063 "<=" 11 10 b f f 1114 1114 16 2065 2064 2055 336 386 )
+insert ( 2064 ">" 11 10 b f f 1114 1114 16 2062 2063 2057 104 108 )
+insert ( 2065 ">=" 11 10 b f f 1114 1114 16 2063 2062 2056 337 398 )
+insert ( 2066 "+" 11 10 b f f 1114 1186 1114 2553 0 2032 - - )
+insert ( 2067 - 11 10 b f f 1114 1114 1186 0 0 2031 - - )
+insert ( 2068 - 11 10 b f f 1114 1186 1114 0 0 2033 - - )
+insert ( 2314 "~<~" 11 10 b f f 25 25 16 2318 2317 2160 103 107 )
+insert ( 2315 "~<=~" 11 10 b f f 25 25 16 2317 2318 2161 336 386 )
+insert ( 2317 "~>=~" 11 10 b f f 25 25 16 2315 2314 2163 337 398 )
+insert ( 2318 "~>~" 11 10 b f f 25 25 16 2314 2315 2164 104 108 )
+insert ( 2326 "~<~" 11 10 b f f 1042 1042 16 2330 2329 2174 103 107 )
+insert ( 2327 "~<=~" 11 10 b f f 1042 1042 16 2329 2330 2175 336 386 )
+insert ( 2329 "~>=~" 11 10 b f f 1042 1042 16 2327 2326 2177 337 398 )
+insert ( 2330 "~>~" 11 10 b f f 1042 1042 16 2326 2327 2178 104 108 )
+insert ( 2345 "<" 11 10 b f f 1082 1114 16 2375 2348 2338 103 107 )
+insert ( 2346 "<=" 11 10 b f f 1082 1114 16 2374 2349 2339 336 386 )
+insert ( 2347 "=" 11 10 b t f 1082 1114 16 2373 2350 2340 101 105 )
+insert ( 2348 ">=" 11 10 b f f 1082 1114 16 2372 2345 2342 337 398 )
+insert ( 2349 ">" 11 10 b f f 1082 1114 16 2371 2346 2341 104 108 )
+insert ( 2350 "<>" 11 10 b f f 1082 1114 16 2376 2347 2343 102 106 )
+insert ( 2358 "<" 11 10 b f f 1082 1184 16 2388 2361 2351 103 107 )
+insert ( 2359 "<=" 11 10 b f f 1082 1184 16 2387 2362 2352 336 386 )
+insert ( 2360 "=" 11 10 b t f 1082 1184 16 2386 2363 2353 101 105 )
+insert ( 2361 ">=" 11 10 b f f 1082 1184 16 2385 2358 2355 337 398 )
+insert ( 2362 ">" 11 10 b f f 1082 1184 16 2384 2359 2354 104 108 )
+insert ( 2363 "<>" 11 10 b f f 1082 1184 16 2389 2360 2356 102 106 )
+insert ( 2371 "<" 11 10 b f f 1114 1082 16 2349 2374 2364 103 107 )
+insert ( 2372 "<=" 11 10 b f f 1114 1082 16 2348 2375 2365 336 386 )
+insert ( 2373 "=" 11 10 b t f 1114 1082 16 2347 2376 2366 101 105 )
+insert ( 2374 ">=" 11 10 b f f 1114 1082 16 2346 2371 2368 337 398 )
+insert ( 2375 ">" 11 10 b f f 1114 1082 16 2345 2372 2367 104 108 )
+insert ( 2376 "<>" 11 10 b f f 1114 1082 16 2350 2373 2369 102 106 )
+insert ( 2384 "<" 11 10 b f f 1184 1082 16 2362 2387 2377 103 107 )
+insert ( 2385 "<=" 11 10 b f f 1184 1082 16 2361 2388 2378 336 386 )
+insert ( 2386 "=" 11 10 b t f 1184 1082 16 2360 2389 2379 101 105 )
+insert ( 2387 ">=" 11 10 b f f 1184 1082 16 2359 2384 2381 337 398 )
+insert ( 2388 ">" 11 10 b f f 1184 1082 16 2358 2385 2380 104 108 )
+insert ( 2389 "<>" 11 10 b f f 1184 1082 16 2363 2386 2382 102 106 )
+insert ( 2534 "<" 11 10 b f f 1114 1184 16 2544 2537 2520 103 107 )
+insert ( 2535 "<=" 11 10 b f f 1114 1184 16 2543 2538 2521 336 386 )
+insert ( 2536 "=" 11 10 b t f 1114 1184 16 2542 2539 2522 101 105 )
+insert ( 2537 ">=" 11 10 b f f 1114 1184 16 2541 2534 2524 337 398 )
+insert ( 2538 ">" 11 10 b f f 1114 1184 16 2540 2535 2523 104 108 )
+insert ( 2539 "<>" 11 10 b f f 1114 1184 16 2545 2536 2525 102 106 )
+insert ( 2540 "<" 11 10 b f f 1184 1114 16 2538 2543 2527 103 107 )
+insert ( 2541 "<=" 11 10 b f f 1184 1114 16 2537 2544 2528 336 386 )
+insert ( 2542 "=" 11 10 b t f 1184 1114 16 2536 2545 2529 101 105 )
+insert ( 2543 ">=" 11 10 b f f 1184 1114 16 2535 2540 2531 337 398 )
+insert ( 2544 ">" 11 10 b f f 1184 1114 16 2534 2541 2530 104 108 )
+insert ( 2545 "<>" 11 10 b f f 1184 1114 16 2539 2542 2532 102 106 )
+insert ( 2551 "+" 11 10 b f f 1186 1082 1114 1076 0 2546 - - )
+insert ( 2552 "+" 11 10 b f f 1186 1266 1266 1802 0 2547 - - )
+insert ( 2553 "+" 11 10 b f f 1186 1114 1114 2066 0 2548 - - )
+insert ( 2554 "+" 11 10 b f f 1186 1184 1184 1327 0 2549 - - )
+insert ( 2555 "+" 11 10 b f f 23 1082 1082 1100 0 2550 - - )
+insert ( 2570 "<<|" 11 10 b f f 603 603 16 0 0 2562 1300 1301 )
+insert ( 2571 "&<|" 11 10 b f f 603 603 16 0 0 2563 1300 1301 )
+insert ( 2572 "|&>" 11 10 b f f 603 603 16 0 0 2564 1300 1301 )
+insert ( 2573 "|>>" 11 10 b f f 603 603 16 0 0 2565 1300 1301 )
+insert ( 2574 "<<|" 11 10 b f f 604 604 16 0 0 2566 1300 1301 )
+insert ( 2575 "&<|" 11 10 b f f 604 604 16 0 0 2567 1300 1301 )
+insert ( 2576 "|&>" 11 10 b f f 604 604 16 0 0 2568 1300 1301 )
+insert ( 2577 "|>>" 11 10 b f f 604 604 16 0 0 2569 1300 1301 )
+insert ( 2589 "&<|" 11 10 b f f 718 718 16 0 0 2587 1300 1301 )
+insert ( 2590 "|&>" 11 10 b f f 718 718 16 0 0 2588 1300 1301 )
+insert ( 2750 "&&" 11 10 b f f 2277 2277 16 2750 0 2747 3817 3818 )
+insert ( 2751 "@>" 11 10 b f f 2277 2277 16 2752 0 2748 3817 3818 )
+insert ( 2752 "<@" 11 10 b f f 2277 2277 16 2751 0 2749 3817 3818 )
+insert ( 2779 "||" 11 10 b f f 25 2776 25 0 0 2003 - - )
+insert ( 2780 "||" 11 10 b f f 2776 25 25 0 0 2004 - - )
+insert ( 2860 "@" 11 10 b f f 604 604 16 2861 0 345 1302 1303 )
+insert ( 2861 "~" 11 10 b f f 604 604 16 2860 0 340 1302 1303 )
+insert ( 2862 "@" 11 10 b f f 603 603 16 2863 0 192 1302 1303 )
+insert ( 2863 "~" 11 10 b f f 603 603 16 2862 0 187 1302 1303 )
+insert ( 2864 "@" 11 10 b f f 718 718 16 2865 0 1458 1302 1303 )
+insert ( 2865 "~" 11 10 b f f 718 718 16 2864 0 1453 1302 1303 )
+insert ( 2866 "@" 11 10 b f f 600 603 16 0 0 136 - - )
+insert ( 2867 "@" 11 10 b f f 600 602 16 2868 0 137 - - )
+insert ( 2868 "~" 11 10 b f f 602 600 16 2867 0 1426 - - )
+insert ( 2869 "@" 11 10 b f f 600 604 16 2870 0 1429 - - )
+insert ( 2870 "~" 11 10 b f f 604 600 16 2869 0 1428 - - )
+insert ( 2871 "@" 11 10 b f f 600 718 16 2872 0 1478 - - )
+insert ( 2872 "~" 11 10 b f f 718 600 16 2871 0 1477 - - )
+insert ( 2873 "@" 11 10 b f f 600 628 16 0 0 959 - - )
+insert ( 2874 "@" 11 10 b f f 600 601 16 0 0 369 - - )
+insert ( 2875 "@" 11 10 b f f 601 628 16 0 0 960 - - )
+insert ( 2876 "@" 11 10 b f f 601 603 16 0 0 372 - - )
+insert ( 2877 "~" 11 10 b f f 1034 1033 16 0 0 1037 - - )
+insert ( 2972 "=" 11 10 b t t 2950 2950 16 2972 2973 2956 101 105 )
+insert ( 2973 "<>" 11 10 b f f 2950 2950 16 2973 2972 2959 102 106 )
+insert ( 2974 "<" 11 10 b f f 2950 2950 16 2975 2977 2954 103 107 )
+insert ( 2975 ">" 11 10 b f f 2950 2950 16 2974 2976 2958 104 108 )
+insert ( 2976 "<=" 11 10 b f f 2950 2950 16 2977 2975 2955 336 386 )
+insert ( 2977 ">=" 11 10 b f f 2950 2950 16 2976 2974 2957 337 398 )
+insert ( 3222 "=" 11 10 b t t 3220 3220 16 3222 3223 3233 101 105 )
+insert ( 3223 "<>" 11 10 b f f 3220 3220 16 3223 3222 3236 102 106 )
+insert ( 3224 "<" 11 10 b f f 3220 3220 16 3225 3227 3231 103 107 )
+insert ( 3225 ">" 11 10 b f f 3220 3220 16 3224 3226 3235 104 108 )
+insert ( 3226 "<=" 11 10 b f f 3220 3220 16 3227 3225 3232 336 386 )
+insert ( 3227 ">=" 11 10 b f f 3220 3220 16 3226 3224 3234 337 398 )
+insert ( 3228 - 11 10 b f f 3220 3220 1700 0 0 3237 - - )
+insert ( 3516 "=" 11 10 b t t 3500 3500 16 3516 3517 3508 101 105 )
+insert ( 3517 "<>" 11 10 b f f 3500 3500 16 3517 3516 3509 102 106 )
+insert ( 3518 "<" 11 10 b f f 3500 3500 16 3519 3521 3510 103 107 )
+insert ( 3519 ">" 11 10 b f f 3500 3500 16 3518 3520 3511 104 108 )
+insert ( 3520 "<=" 11 10 b f f 3500 3500 16 3521 3519 3512 336 386 )
+insert ( 3521 ">=" 11 10 b f f 3500 3500 16 3520 3518 3513 337 398 )
+insert ( 3627 "<" 11 10 b f f 3614 3614 16 3632 3631 3616 103 107 )
+insert ( 3628 "<=" 11 10 b f f 3614 3614 16 3631 3632 3617 336 386 )
+insert ( 3629 "=" 11 10 b t f 3614 3614 16 3629 3630 3618 101 105 )
+insert ( 3630 "<>" 11 10 b f f 3614 3614 16 3630 3629 3619 102 106 )
+insert ( 3631 ">=" 11 10 b f f 3614 3614 16 3628 3627 3620 337 398 )
+insert ( 3632 ">" 11 10 b f f 3614 3614 16 3627 3628 3621 104 108 )
+insert ( 3633 "||" 11 10 b f f 3614 3614 3614 0 0 3625 - - )
+insert ( 3636 "@@" 11 10 b f f 3614 3615 16 3637 0 3634 3686 3687 )
+insert ( 3637 "@@" 11 10 b f f 3615 3614 16 3636 0 3635 3686 3687 )
+insert ( 3660 "@@@" 11 10 b f f 3614 3615 16 3661 0 3634 3686 3687 )
+insert ( 3661 "@@@" 11 10 b f f 3615 3614 16 3660 0 3635 3686 3687 )
+insert ( 3674 "<" 11 10 b f f 3615 3615 16 3679 3678 3662 103 107 )
+insert ( 3675 "<=" 11 10 b f f 3615 3615 16 3678 3679 3663 336 386 )
+insert ( 3676 "=" 11 10 b t f 3615 3615 16 3676 3677 3664 101 105 )
+insert ( 3677 "<>" 11 10 b f f 3615 3615 16 3677 3676 3665 102 106 )
+insert ( 3678 ">=" 11 10 b f f 3615 3615 16 3675 3674 3666 337 398 )
+insert ( 3679 ">" 11 10 b f f 3615 3615 16 3674 3675 3667 104 108 )
+insert ( 3680 "&&" 11 10 b f f 3615 3615 3615 0 0 3669 - - )
+insert ( 3681 "||" 11 10 b f f 3615 3615 3615 0 0 3670 - - )
+insert ( 5005 "<->" 11 10 b f f 3615 3615 3615 0 0 5003 - - )
+insert ( 3682 "!!" 11 10 l f f 0 3615 3615 0 0 3671 - - )
+insert ( 3693 "@>" 11 10 b f f 3615 3615 16 3694 0 3691 5040 5041 )
+insert ( 3694 "<@" 11 10 b f f 3615 3615 16 3693 0 3692 5040 5041 )
+insert ( 3762 "@@" 11 10 b f f 25 25 16 0 0 3760 5040 5041 )
+insert ( 3763 "@@" 11 10 b f f 25 3615 16 0 0 3761 5040 5041 )
+insert ( 2988 "=" 11 10 b t f 2249 2249 16 2988 2989 2981 101 105 )
+insert ( 2989 "<>" 11 10 b f f 2249 2249 16 2989 2988 2982 102 106 )
+insert ( 2990 "<" 11 10 b f f 2249 2249 16 2991 2993 2983 103 107 )
+insert ( 2991 ">" 11 10 b f f 2249 2249 16 2990 2992 2984 104 108 )
+insert ( 2992 "<=" 11 10 b f f 2249 2249 16 2993 2991 2985 336 386 )
+insert ( 2993 ">=" 11 10 b f f 2249 2249 16 2992 2990 2986 337 398 )
+insert ( 3188 "*=" 11 10 b t f 2249 2249 16 3188 3189 3181 101 105 )
+insert ( 3189 "*<>" 11 10 b f f 2249 2249 16 3189 3188 3182 102 106 )
+insert ( 3190 "*<" 11 10 b f f 2249 2249 16 3191 3193 3183 103 107 )
+insert ( 3191 "*>" 11 10 b f f 2249 2249 16 3190 3192 3184 104 108 )
+insert ( 3192 "*<=" 11 10 b f f 2249 2249 16 3193 3191 3185 336 386 )
+insert ( 3193 "*>=" 11 10 b f f 2249 2249 16 3192 3190 3186 337 398 )
+insert ( 3882 "=" 11 10 b t t 3831 3831 16 3882 3883 3855 101 105 )
+insert ( 3883 "<>" 11 10 b f f 3831 3831 16 3883 3882 3856 102 106 )
+insert ( 3884 "<" 11 10 b f f 3831 3831 16 3887 3886 3871 3169 107 )
+insert ( 3885 "<=" 11 10 b f f 3831 3831 16 3886 3887 3872 3169 386 )
+insert ( 3886 ">=" 11 10 b f f 3831 3831 16 3885 3884 3873 3169 398 )
+insert ( 3887 ">" 11 10 b f f 3831 3831 16 3884 3885 3874 3169 108 )
+insert ( 3888 "&&" 11 10 b f f 3831 3831 16 3888 0 3857 3169 140 )
+insert ( 3889 "@>" 11 10 b f f 3831 2283 16 3891 0 3858 3169 1303 )
+insert ( 3890 "@>" 11 10 b f f 3831 3831 16 3892 0 3859 3169 1303 )
+insert ( 3891 "<@" 11 10 b f f 2283 3831 16 3889 0 3860 3169 1303 )
+insert ( 3892 "<@" 11 10 b f f 3831 3831 16 3890 0 3861 3169 1303 )
+insert ( 3893 "<<" 11 10 b f f 3831 3831 16 3894 0 3863 3169 107 )
+insert ( 3894 ">>" 11 10 b f f 3831 3831 16 3893 0 3864 3169 108 )
+insert ( 3895 "&<" 11 10 b f f 3831 3831 16 0 0 3865 3169 107 )
+insert ( 3896 "&>" 11 10 b f f 3831 3831 16 0 0 3866 3169 108 )
+insert ( 3897 "-|-" 11 10 b f f 3831 3831 16 3897 0 3862 5040 5041 )
+insert ( 3898 "+" 11 10 b f f 3831 3831 3831 3898 0 3867 - - )
+insert ( 3899 - 11 10 b f f 3831 3831 3831 0 0 3869 - - )
+insert ( 3900 "*" 11 10 b f f 3831 3831 3831 3900 0 3868 - - )
+insert ( 3962 "->" 11 10 b f f 114 25 114 0 0 3947 - - )
+insert ( 3963 "->>" 11 10 b f f 114 25 25 0 0 3948 - - )
+insert ( 3964 "->" 11 10 b f f 114 23 114 0 0 3949 - - )
+insert ( 3965 "->>" 11 10 b f f 114 23 25 0 0 3950 - - )
+insert ( 3966 "#>" 11 10 b f f 114 1009 114 0 0 3951 - - )
+insert ( 3967 "#>>" 11 10 b f f 114 1009 25 0 0 3953 - - )
+insert ( 3211 "->" 11 10 b f f 3802 25 3802 0 0 3478 - - )
+insert ( 3477 "->>" 11 10 b f f 3802 25 25 0 0 3214 - - )
+insert ( 3212 "->" 11 10 b f f 3802 23 3802 0 0 3215 - - )
+insert ( 3481 "->>" 11 10 b f f 3802 23 25 0 0 3216 - - )
+insert ( 3213 "#>" 11 10 b f f 3802 1009 3802 0 0 3217 - - )
+insert ( 3206 "#>>" 11 10 b f f 3802 1009 25 0 0 3940 - - )
+insert ( 3240 "=" 11 10 b t t 3802 3802 16 3240 3241 4043 101 105 )
+insert ( 3241 "<>" 11 10 b f f 3802 3802 16 3241 3240 4038 102 106 )
+insert ( 3242 "<" 11 10 b f f 3802 3802 16 3243 3245 4039 103 107 )
+insert ( 3243 ">" 11 10 b f f 3802 3802 16 3242 3244 4040 104 108 )
+insert ( 3244 "<=" 11 10 b f f 3802 3802 16 3245 3243 4041 336 386 )
+insert ( 3245 ">=" 11 10 b f f 3802 3802 16 3244 3242 4042 337 398 )
+insert ( 3246 "@>" 11 10 b f f 3802 3802 16 3250 0 4046 5040 5041 )
+insert ( 3247 "?" 11 10 b f f 3802 25 16 0 0 4047 5040 5041 )
+insert ( 3248 "?|" 11 10 b f f 3802 1009 16 0 0 4048 5040 5041 )
+insert ( 3249 "?&" 11 10 b f f 3802 1009 16 0 0 4049 5040 5041 )
+insert ( 3250 "<@" 11 10 b f f 3802 3802 16 3246 0 4050 5040 5041 )
+insert ( 3284 "||" 11 10 b f f 3802 3802 3802 0 0 3301 - - )
+insert ( 3285 - 11 10 b f f 3802 25 3802 0 0 3302 - - )
+insert ( 3398 - 11 10 b f f 3802 1009 3802 0 0 3343 - - )
+insert ( 3286 - 11 10 b f f 3802 23 3802 0 0 3303 - - )
+insert ( 3287 "#-" 11 10 b f f 3802 1009 3802 0 0 3304 - - )
+insert ( 4012 "@?" 11 10 b f f 3802 4072 16 0 0 4010 5040 5041 )
+insert ( 4013 "@@" 11 10 b f f 3802 4072 16 0 0 4011 5040 5041 )
+close pg_operator
+create pg_opfamily 2753
+ (
+ oid = oid ,
+ opfmethod = oid ,
+ opfname = name ,
+ opfnamespace = oid ,
+ opfowner = oid
+ )
+open pg_opfamily
+insert ( 397 403 array_ops 11 10 )
+insert ( 627 405 array_ops 11 10 )
+insert ( 423 403 bit_ops 11 10 )
+insert ( 424 403 bool_ops 11 10 )
+insert ( 426 403 bpchar_ops 11 10 )
+insert ( 427 405 bpchar_ops 11 10 )
+insert ( 428 403 bytea_ops 11 10 )
+insert ( 429 403 char_ops 11 10 )
+insert ( 431 405 char_ops 11 10 )
+insert ( 434 403 datetime_ops 11 10 )
+insert ( 435 405 date_ops 11 10 )
+insert ( 1970 403 float_ops 11 10 )
+insert ( 1971 405 float_ops 11 10 )
+insert ( 1974 403 network_ops 11 10 )
+insert ( 1975 405 network_ops 11 10 )
+insert ( 3550 783 network_ops 11 10 )
+insert ( 3794 4000 network_ops 11 10 )
+insert ( 1976 403 integer_ops 11 10 )
+insert ( 1977 405 integer_ops 11 10 )
+insert ( 1982 403 interval_ops 11 10 )
+insert ( 1983 405 interval_ops 11 10 )
+insert ( 1984 403 macaddr_ops 11 10 )
+insert ( 1985 405 macaddr_ops 11 10 )
+insert ( 3371 403 macaddr8_ops 11 10 )
+insert ( 3372 405 macaddr8_ops 11 10 )
+insert ( 1988 403 numeric_ops 11 10 )
+insert ( 1998 405 numeric_ops 11 10 )
+insert ( 1989 403 oid_ops 11 10 )
+insert ( 1990 405 oid_ops 11 10 )
+insert ( 1991 403 oidvector_ops 11 10 )
+insert ( 1992 405 oidvector_ops 11 10 )
+insert ( 2994 403 record_ops 11 10 )
+insert ( 3194 403 record_image_ops 11 10 )
+insert ( 1994 403 text_ops 11 10 )
+insert ( 1995 405 text_ops 11 10 )
+insert ( 1996 403 time_ops 11 10 )
+insert ( 1997 405 time_ops 11 10 )
+insert ( 1999 405 timestamptz_ops 11 10 )
+insert ( 2000 403 timetz_ops 11 10 )
+insert ( 2001 405 timetz_ops 11 10 )
+insert ( 2002 403 varbit_ops 11 10 )
+insert ( 2040 405 timestamp_ops 11 10 )
+insert ( 2095 403 text_pattern_ops 11 10 )
+insert ( 2097 403 bpchar_pattern_ops 11 10 )
+insert ( 2099 403 money_ops 11 10 )
+insert ( 2222 405 bool_ops 11 10 )
+insert ( 2223 405 bytea_ops 11 10 )
+insert ( 2789 403 tid_ops 11 10 )
+insert ( 2225 405 xid_ops 11 10 )
+insert ( 5032 405 xid8_ops 11 10 )
+insert ( 5067 403 xid8_ops 11 10 )
+insert ( 2226 405 cid_ops 11 10 )
+insert ( 2227 405 tid_ops 11 10 )
+insert ( 2229 405 text_pattern_ops 11 10 )
+insert ( 2231 405 bpchar_pattern_ops 11 10 )
+insert ( 2235 405 aclitem_ops 11 10 )
+insert ( 2593 783 box_ops 11 10 )
+insert ( 2594 783 poly_ops 11 10 )
+insert ( 2595 783 circle_ops 11 10 )
+insert ( 1029 783 point_ops 11 10 )
+insert ( 2745 2742 array_ops 11 10 )
+insert ( 2968 403 uuid_ops 11 10 )
+insert ( 2969 405 uuid_ops 11 10 )
+insert ( 3253 403 pg_lsn_ops 11 10 )
+insert ( 3254 405 pg_lsn_ops 11 10 )
+insert ( 3522 403 enum_ops 11 10 )
+insert ( 3523 405 enum_ops 11 10 )
+insert ( 3626 403 tsvector_ops 11 10 )
+insert ( 3655 783 tsvector_ops 11 10 )
+insert ( 3659 2742 tsvector_ops 11 10 )
+insert ( 3683 403 tsquery_ops 11 10 )
+insert ( 3702 783 tsquery_ops 11 10 )
+insert ( 3901 403 range_ops 11 10 )
+insert ( 3903 405 range_ops 11 10 )
+insert ( 3919 783 range_ops 11 10 )
+insert ( 3474 4000 range_ops 11 10 )
+insert ( 4015 4000 quad_point_ops 11 10 )
+insert ( 4016 4000 kd_point_ops 11 10 )
+insert ( 4017 4000 text_ops 11 10 )
+insert ( 4033 403 jsonb_ops 11 10 )
+insert ( 4034 405 jsonb_ops 11 10 )
+insert ( 4036 2742 jsonb_ops 11 10 )
+insert ( 4037 2742 jsonb_path_ops 11 10 )
+insert ( 4054 3580 integer_minmax_ops 11 10 )
+insert ( 4055 3580 numeric_minmax_ops 11 10 )
+insert ( 4056 3580 text_minmax_ops 11 10 )
+insert ( 4058 3580 timetz_minmax_ops 11 10 )
+insert ( 4059 3580 datetime_minmax_ops 11 10 )
+insert ( 4062 3580 char_minmax_ops 11 10 )
+insert ( 4064 3580 bytea_minmax_ops 11 10 )
+insert ( 4065 3580 name_minmax_ops 11 10 )
+insert ( 4068 3580 oid_minmax_ops 11 10 )
+insert ( 4069 3580 tid_minmax_ops 11 10 )
+insert ( 4070 3580 float_minmax_ops 11 10 )
+insert ( 4074 3580 macaddr_minmax_ops 11 10 )
+insert ( 4109 3580 macaddr8_minmax_ops 11 10 )
+insert ( 4075 3580 network_minmax_ops 11 10 )
+insert ( 4102 3580 network_inclusion_ops 11 10 )
+insert ( 4076 3580 bpchar_minmax_ops 11 10 )
+insert ( 4077 3580 time_minmax_ops 11 10 )
+insert ( 4078 3580 interval_minmax_ops 11 10 )
+insert ( 4079 3580 bit_minmax_ops 11 10 )
+insert ( 4080 3580 varbit_minmax_ops 11 10 )
+insert ( 4081 3580 uuid_minmax_ops 11 10 )
+insert ( 4103 3580 range_inclusion_ops 11 10 )
+insert ( 4082 3580 pg_lsn_minmax_ops 11 10 )
+insert ( 4104 3580 box_inclusion_ops 11 10 )
+insert ( 5000 4000 box_ops 11 10 )
+insert ( 5008 4000 poly_ops 11 10 )
+close pg_opfamily
+create pg_opclass 2616
+ (
+ oid = oid ,
+ opcmethod = oid ,
+ opcname = name ,
+ opcnamespace = oid ,
+ opcowner = oid ,
+ opcfamily = oid ,
+ opcintype = oid ,
+ opcdefault = bool ,
+ opckeytype = oid
+ )
+open pg_opclass
+insert ( 10000 403 array_ops 11 10 397 2277 t 0 )
+insert ( 10001 405 array_ops 11 10 627 2277 t 0 )
+insert ( 10002 403 bit_ops 11 10 423 1560 t 0 )
+insert ( 10003 403 bool_ops 11 10 424 16 t 0 )
+insert ( 10004 403 bpchar_ops 11 10 426 1042 t 0 )
+insert ( 10005 405 bpchar_ops 11 10 427 1042 t 0 )
+insert ( 10006 403 bytea_ops 11 10 428 17 t 0 )
+insert ( 10007 403 char_ops 11 10 429 18 t 0 )
+insert ( 10008 405 char_ops 11 10 431 18 t 0 )
+insert ( 10009 403 cidr_ops 11 10 1974 869 f 0 )
+insert ( 10010 405 cidr_ops 11 10 1975 869 f 0 )
+insert ( 3122 403 date_ops 11 10 434 1082 t 0 )
+insert ( 10011 405 date_ops 11 10 435 1082 t 0 )
+insert ( 10012 403 float4_ops 11 10 1970 700 t 0 )
+insert ( 10013 405 float4_ops 11 10 1971 700 t 0 )
+insert ( 3123 403 float8_ops 11 10 1970 701 t 0 )
+insert ( 10014 405 float8_ops 11 10 1971 701 t 0 )
+insert ( 10015 403 inet_ops 11 10 1974 869 t 0 )
+insert ( 10016 405 inet_ops 11 10 1975 869 t 0 )
+insert ( 10017 783 inet_ops 11 10 3550 869 f 0 )
+insert ( 10018 4000 inet_ops 11 10 3794 869 t 0 )
+insert ( 1979 403 int2_ops 11 10 1976 21 t 0 )
+insert ( 10019 405 int2_ops 11 10 1977 21 t 0 )
+insert ( 1978 403 int4_ops 11 10 1976 23 t 0 )
+insert ( 10020 405 int4_ops 11 10 1977 23 t 0 )
+insert ( 3124 403 int8_ops 11 10 1976 20 t 0 )
+insert ( 10021 405 int8_ops 11 10 1977 20 t 0 )
+insert ( 10022 403 interval_ops 11 10 1982 1186 t 0 )
+insert ( 10023 405 interval_ops 11 10 1983 1186 t 0 )
+insert ( 10024 403 macaddr_ops 11 10 1984 829 t 0 )
+insert ( 10025 405 macaddr_ops 11 10 1985 829 t 0 )
+insert ( 10026 403 macaddr8_ops 11 10 3371 774 t 0 )
+insert ( 10027 405 macaddr8_ops 11 10 3372 774 t 0 )
+insert ( 10028 403 name_ops 11 10 1994 19 t 2275 )
+insert ( 10029 405 name_ops 11 10 1995 19 t 0 )
+insert ( 3125 403 numeric_ops 11 10 1988 1700 t 0 )
+insert ( 10030 405 numeric_ops 11 10 1998 1700 t 0 )
+insert ( 1981 403 oid_ops 11 10 1989 26 t 0 )
+insert ( 10031 405 oid_ops 11 10 1990 26 t 0 )
+insert ( 10032 403 oidvector_ops 11 10 1991 30 t 0 )
+insert ( 10033 405 oidvector_ops 11 10 1992 30 t 0 )
+insert ( 10034 403 record_ops 11 10 2994 2249 t 0 )
+insert ( 10035 403 record_image_ops 11 10 3194 2249 f 0 )
+insert ( 3126 403 text_ops 11 10 1994 25 t 0 )
+insert ( 10036 405 text_ops 11 10 1995 25 t 0 )
+insert ( 10037 403 time_ops 11 10 1996 1083 t 0 )
+insert ( 10038 405 time_ops 11 10 1997 1083 t 0 )
+insert ( 3127 403 timestamptz_ops 11 10 434 1184 t 0 )
+insert ( 10039 405 timestamptz_ops 11 10 1999 1184 t 0 )
+insert ( 10040 403 timetz_ops 11 10 2000 1266 t 0 )
+insert ( 10041 405 timetz_ops 11 10 2001 1266 t 0 )
+insert ( 10042 403 varbit_ops 11 10 2002 1562 t 0 )
+insert ( 10043 403 varchar_ops 11 10 1994 25 f 0 )
+insert ( 10044 405 varchar_ops 11 10 1995 25 f 0 )
+insert ( 3128 403 timestamp_ops 11 10 434 1114 t 0 )
+insert ( 10045 405 timestamp_ops 11 10 2040 1114 t 0 )
+insert ( 4217 403 text_pattern_ops 11 10 2095 25 f 0 )
+insert ( 4218 403 varchar_pattern_ops 11 10 2095 25 f 0 )
+insert ( 4219 403 bpchar_pattern_ops 11 10 2097 1042 f 0 )
+insert ( 10046 403 money_ops 11 10 2099 790 t 0 )
+insert ( 10047 405 bool_ops 11 10 2222 16 t 0 )
+insert ( 10048 405 bytea_ops 11 10 2223 17 t 0 )
+insert ( 10049 403 tid_ops 11 10 2789 27 t 0 )
+insert ( 10050 405 xid_ops 11 10 2225 28 t 0 )
+insert ( 10051 405 xid8_ops 11 10 5032 5069 t 0 )
+insert ( 10052 403 xid8_ops 11 10 5067 5069 t 0 )
+insert ( 10053 405 cid_ops 11 10 2226 29 t 0 )
+insert ( 10054 405 tid_ops 11 10 2227 27 t 0 )
+insert ( 10055 405 text_pattern_ops 11 10 2229 25 f 0 )
+insert ( 10056 405 varchar_pattern_ops 11 10 2229 25 f 0 )
+insert ( 10057 405 bpchar_pattern_ops 11 10 2231 1042 f 0 )
+insert ( 10058 405 aclitem_ops 11 10 2235 1033 t 0 )
+insert ( 10059 783 box_ops 11 10 2593 603 t 0 )
+insert ( 10060 783 point_ops 11 10 1029 600 t 603 )
+insert ( 10061 783 poly_ops 11 10 2594 604 t 603 )
+insert ( 10062 783 circle_ops 11 10 2595 718 t 603 )
+insert ( 10063 2742 array_ops 11 10 2745 2277 t 2283 )
+insert ( 10064 403 uuid_ops 11 10 2968 2950 t 0 )
+insert ( 10065 405 uuid_ops 11 10 2969 2950 t 0 )
+insert ( 10066 403 pg_lsn_ops 11 10 3253 3220 t 0 )
+insert ( 10067 405 pg_lsn_ops 11 10 3254 3220 t 0 )
+insert ( 10068 403 enum_ops 11 10 3522 3500 t 0 )
+insert ( 10069 405 enum_ops 11 10 3523 3500 t 0 )
+insert ( 10070 403 tsvector_ops 11 10 3626 3614 t 0 )
+insert ( 10071 783 tsvector_ops 11 10 3655 3614 t 3642 )
+insert ( 10072 2742 tsvector_ops 11 10 3659 3614 t 25 )
+insert ( 10073 403 tsquery_ops 11 10 3683 3615 t 0 )
+insert ( 10074 783 tsquery_ops 11 10 3702 3615 t 20 )
+insert ( 10075 403 range_ops 11 10 3901 3831 t 0 )
+insert ( 10076 405 range_ops 11 10 3903 3831 t 0 )
+insert ( 10077 783 range_ops 11 10 3919 3831 t 0 )
+insert ( 10078 4000 range_ops 11 10 3474 3831 t 0 )
+insert ( 10079 4000 box_ops 11 10 5000 603 t 0 )
+insert ( 10080 4000 quad_point_ops 11 10 4015 600 t 0 )
+insert ( 10081 4000 kd_point_ops 11 10 4016 600 f 0 )
+insert ( 10082 4000 text_ops 11 10 4017 25 t 0 )
+insert ( 10083 4000 poly_ops 11 10 5008 604 t 603 )
+insert ( 10084 403 jsonb_ops 11 10 4033 3802 t 0 )
+insert ( 10085 405 jsonb_ops 11 10 4034 3802 t 0 )
+insert ( 10086 2742 jsonb_ops 11 10 4036 3802 t 25 )
+insert ( 10087 2742 jsonb_path_ops 11 10 4037 3802 f 23 )
+insert ( 10088 3580 bytea_minmax_ops 11 10 4064 17 t 17 )
+insert ( 10089 3580 char_minmax_ops 11 10 4062 18 t 18 )
+insert ( 10090 3580 name_minmax_ops 11 10 4065 19 t 19 )
+insert ( 10091 3580 int8_minmax_ops 11 10 4054 20 t 20 )
+insert ( 10092 3580 int2_minmax_ops 11 10 4054 21 t 21 )
+insert ( 10093 3580 int4_minmax_ops 11 10 4054 23 t 23 )
+insert ( 10094 3580 text_minmax_ops 11 10 4056 25 t 25 )
+insert ( 10095 3580 oid_minmax_ops 11 10 4068 26 t 26 )
+insert ( 10096 3580 tid_minmax_ops 11 10 4069 27 t 27 )
+insert ( 10097 3580 float4_minmax_ops 11 10 4070 700 t 700 )
+insert ( 10098 3580 float8_minmax_ops 11 10 4070 701 t 701 )
+insert ( 10099 3580 macaddr_minmax_ops 11 10 4074 829 t 829 )
+insert ( 10100 3580 macaddr8_minmax_ops 11 10 4109 774 t 774 )
+insert ( 10101 3580 inet_minmax_ops 11 10 4075 869 f 869 )
+insert ( 10102 3580 inet_inclusion_ops 11 10 4102 869 t 869 )
+insert ( 10103 3580 bpchar_minmax_ops 11 10 4076 1042 t 1042 )
+insert ( 10104 3580 time_minmax_ops 11 10 4077 1083 t 1083 )
+insert ( 10105 3580 date_minmax_ops 11 10 4059 1082 t 1082 )
+insert ( 10106 3580 timestamp_minmax_ops 11 10 4059 1114 t 1114 )
+insert ( 10107 3580 timestamptz_minmax_ops 11 10 4059 1184 t 1184 )
+insert ( 10108 3580 interval_minmax_ops 11 10 4078 1186 t 1186 )
+insert ( 10109 3580 timetz_minmax_ops 11 10 4058 1266 t 1266 )
+insert ( 10110 3580 bit_minmax_ops 11 10 4079 1560 t 1560 )
+insert ( 10111 3580 varbit_minmax_ops 11 10 4080 1562 t 1562 )
+insert ( 10112 3580 numeric_minmax_ops 11 10 4055 1700 t 1700 )
+insert ( 10113 3580 uuid_minmax_ops 11 10 4081 2950 t 2950 )
+insert ( 10114 3580 range_inclusion_ops 11 10 4103 3831 t 3831 )
+insert ( 10115 3580 pg_lsn_minmax_ops 11 10 4082 3220 t 3220 )
+insert ( 10116 3580 box_inclusion_ops 11 10 4104 603 t 603 )
+close pg_opclass
+create pg_am 2601
+ (
+ oid = oid ,
+ amname = name ,
+ amhandler = regproc ,
+ amtype = char
+ )
+open pg_am
+insert ( 2 heap 3 t )
+insert ( 403 btree 330 i )
+insert ( 405 hash 331 i )
+insert ( 783 gist 332 i )
+insert ( 2742 gin 333 i )
+insert ( 4000 spgist 334 i )
+insert ( 3580 brin 335 i )
+close pg_am
+create pg_amop 2602
+ (
+ oid = oid ,
+ amopfamily = oid ,
+ amoplefttype = oid ,
+ amoprighttype = oid ,
+ amopstrategy = int2 ,
+ amoppurpose = char ,
+ amopopr = oid ,
+ amopmethod = oid ,
+ amopsortfamily = oid
+ )
+open pg_amop
+insert ( 10117 1976 21 21 1 s 95 403 0 )
+insert ( 10118 1976 21 21 2 s 522 403 0 )
+insert ( 10119 1976 21 21 3 s 94 403 0 )
+insert ( 10120 1976 21 21 4 s 524 403 0 )
+insert ( 10121 1976 21 21 5 s 520 403 0 )
+insert ( 10122 1976 21 23 1 s 534 403 0 )
+insert ( 10123 1976 21 23 2 s 540 403 0 )
+insert ( 10124 1976 21 23 3 s 532 403 0 )
+insert ( 10125 1976 21 23 4 s 542 403 0 )
+insert ( 10126 1976 21 23 5 s 536 403 0 )
+insert ( 10127 1976 21 20 1 s 1864 403 0 )
+insert ( 10128 1976 21 20 2 s 1866 403 0 )
+insert ( 10129 1976 21 20 3 s 1862 403 0 )
+insert ( 10130 1976 21 20 4 s 1867 403 0 )
+insert ( 10131 1976 21 20 5 s 1865 403 0 )
+insert ( 10132 1976 23 23 1 s 97 403 0 )
+insert ( 10133 1976 23 23 2 s 523 403 0 )
+insert ( 10134 1976 23 23 3 s 96 403 0 )
+insert ( 10135 1976 23 23 4 s 525 403 0 )
+insert ( 10136 1976 23 23 5 s 521 403 0 )
+insert ( 10137 1976 23 21 1 s 535 403 0 )
+insert ( 10138 1976 23 21 2 s 541 403 0 )
+insert ( 10139 1976 23 21 3 s 533 403 0 )
+insert ( 10140 1976 23 21 4 s 543 403 0 )
+insert ( 10141 1976 23 21 5 s 537 403 0 )
+insert ( 10142 1976 23 20 1 s 37 403 0 )
+insert ( 10143 1976 23 20 2 s 80 403 0 )
+insert ( 10144 1976 23 20 3 s 15 403 0 )
+insert ( 10145 1976 23 20 4 s 82 403 0 )
+insert ( 10146 1976 23 20 5 s 76 403 0 )
+insert ( 10147 1976 20 20 1 s 412 403 0 )
+insert ( 10148 1976 20 20 2 s 414 403 0 )
+insert ( 10149 1976 20 20 3 s 410 403 0 )
+insert ( 10150 1976 20 20 4 s 415 403 0 )
+insert ( 10151 1976 20 20 5 s 413 403 0 )
+insert ( 10152 1976 20 21 1 s 1870 403 0 )
+insert ( 10153 1976 20 21 2 s 1872 403 0 )
+insert ( 10154 1976 20 21 3 s 1868 403 0 )
+insert ( 10155 1976 20 21 4 s 1873 403 0 )
+insert ( 10156 1976 20 21 5 s 1871 403 0 )
+insert ( 10157 1976 20 23 1 s 418 403 0 )
+insert ( 10158 1976 20 23 2 s 420 403 0 )
+insert ( 10159 1976 20 23 3 s 416 403 0 )
+insert ( 10160 1976 20 23 4 s 430 403 0 )
+insert ( 10161 1976 20 23 5 s 419 403 0 )
+insert ( 10162 1989 26 26 1 s 609 403 0 )
+insert ( 10163 1989 26 26 2 s 611 403 0 )
+insert ( 10164 1989 26 26 3 s 607 403 0 )
+insert ( 10165 1989 26 26 4 s 612 403 0 )
+insert ( 10166 1989 26 26 5 s 610 403 0 )
+insert ( 10167 5067 5069 5069 1 s 5073 403 0 )
+insert ( 10168 5067 5069 5069 2 s 5075 403 0 )
+insert ( 10169 5067 5069 5069 3 s 5068 403 0 )
+insert ( 10170 5067 5069 5069 4 s 5076 403 0 )
+insert ( 10171 5067 5069 5069 5 s 5074 403 0 )
+insert ( 10172 2789 27 27 1 s 2799 403 0 )
+insert ( 10173 2789 27 27 2 s 2801 403 0 )
+insert ( 10174 2789 27 27 3 s 387 403 0 )
+insert ( 10175 2789 27 27 4 s 2802 403 0 )
+insert ( 10176 2789 27 27 5 s 2800 403 0 )
+insert ( 10177 1991 30 30 1 s 645 403 0 )
+insert ( 10178 1991 30 30 2 s 647 403 0 )
+insert ( 10179 1991 30 30 3 s 649 403 0 )
+insert ( 10180 1991 30 30 4 s 648 403 0 )
+insert ( 10181 1991 30 30 5 s 646 403 0 )
+insert ( 10182 1970 700 700 1 s 622 403 0 )
+insert ( 10183 1970 700 700 2 s 624 403 0 )
+insert ( 10184 1970 700 700 3 s 620 403 0 )
+insert ( 10185 1970 700 700 4 s 625 403 0 )
+insert ( 10186 1970 700 700 5 s 623 403 0 )
+insert ( 10187 1970 700 701 1 s 1122 403 0 )
+insert ( 10188 1970 700 701 2 s 1124 403 0 )
+insert ( 10189 1970 700 701 3 s 1120 403 0 )
+insert ( 10190 1970 700 701 4 s 1125 403 0 )
+insert ( 10191 1970 700 701 5 s 1123 403 0 )
+insert ( 10192 1970 701 701 1 s 672 403 0 )
+insert ( 10193 1970 701 701 2 s 673 403 0 )
+insert ( 10194 1970 701 701 3 s 670 403 0 )
+insert ( 10195 1970 701 701 4 s 675 403 0 )
+insert ( 10196 1970 701 701 5 s 674 403 0 )
+insert ( 10197 1970 701 700 1 s 1132 403 0 )
+insert ( 10198 1970 701 700 2 s 1134 403 0 )
+insert ( 10199 1970 701 700 3 s 1130 403 0 )
+insert ( 10200 1970 701 700 4 s 1135 403 0 )
+insert ( 10201 1970 701 700 5 s 1133 403 0 )
+insert ( 10202 429 18 18 1 s 631 403 0 )
+insert ( 10203 429 18 18 2 s 632 403 0 )
+insert ( 10204 429 18 18 3 s 92 403 0 )
+insert ( 10205 429 18 18 4 s 634 403 0 )
+insert ( 10206 429 18 18 5 s 633 403 0 )
+insert ( 10207 1994 25 25 1 s 664 403 0 )
+insert ( 10208 1994 25 25 2 s 665 403 0 )
+insert ( 10209 1994 25 25 3 s 98 403 0 )
+insert ( 10210 1994 25 25 4 s 667 403 0 )
+insert ( 10211 1994 25 25 5 s 666 403 0 )
+insert ( 10212 1994 19 19 1 s 660 403 0 )
+insert ( 10213 1994 19 19 2 s 661 403 0 )
+insert ( 10214 1994 19 19 3 s 93 403 0 )
+insert ( 10215 1994 19 19 4 s 663 403 0 )
+insert ( 10216 1994 19 19 5 s 662 403 0 )
+insert ( 10217 1994 19 25 1 s 255 403 0 )
+insert ( 10218 1994 19 25 2 s 256 403 0 )
+insert ( 10219 1994 19 25 3 s 254 403 0 )
+insert ( 10220 1994 19 25 4 s 257 403 0 )
+insert ( 10221 1994 19 25 5 s 258 403 0 )
+insert ( 10222 1994 25 19 1 s 261 403 0 )
+insert ( 10223 1994 25 19 2 s 262 403 0 )
+insert ( 10224 1994 25 19 3 s 260 403 0 )
+insert ( 10225 1994 25 19 4 s 263 403 0 )
+insert ( 10226 1994 25 19 5 s 264 403 0 )
+insert ( 10227 426 1042 1042 1 s 1058 403 0 )
+insert ( 10228 426 1042 1042 2 s 1059 403 0 )
+insert ( 10229 426 1042 1042 3 s 1054 403 0 )
+insert ( 10230 426 1042 1042 4 s 1061 403 0 )
+insert ( 10231 426 1042 1042 5 s 1060 403 0 )
+insert ( 10232 428 17 17 1 s 1957 403 0 )
+insert ( 10233 428 17 17 2 s 1958 403 0 )
+insert ( 10234 428 17 17 3 s 1955 403 0 )
+insert ( 10235 428 17 17 4 s 1960 403 0 )
+insert ( 10236 428 17 17 5 s 1959 403 0 )
+insert ( 10237 434 1082 1082 1 s 1095 403 0 )
+insert ( 10238 434 1082 1082 2 s 1096 403 0 )
+insert ( 10239 434 1082 1082 3 s 1093 403 0 )
+insert ( 10240 434 1082 1082 4 s 1098 403 0 )
+insert ( 10241 434 1082 1082 5 s 1097 403 0 )
+insert ( 10242 434 1082 1114 1 s 2345 403 0 )
+insert ( 10243 434 1082 1114 2 s 2346 403 0 )
+insert ( 10244 434 1082 1114 3 s 2347 403 0 )
+insert ( 10245 434 1082 1114 4 s 2348 403 0 )
+insert ( 10246 434 1082 1114 5 s 2349 403 0 )
+insert ( 10247 434 1082 1184 1 s 2358 403 0 )
+insert ( 10248 434 1082 1184 2 s 2359 403 0 )
+insert ( 10249 434 1082 1184 3 s 2360 403 0 )
+insert ( 10250 434 1082 1184 4 s 2361 403 0 )
+insert ( 10251 434 1082 1184 5 s 2362 403 0 )
+insert ( 10252 434 1114 1114 1 s 2062 403 0 )
+insert ( 10253 434 1114 1114 2 s 2063 403 0 )
+insert ( 10254 434 1114 1114 3 s 2060 403 0 )
+insert ( 10255 434 1114 1114 4 s 2065 403 0 )
+insert ( 10256 434 1114 1114 5 s 2064 403 0 )
+insert ( 10257 434 1114 1082 1 s 2371 403 0 )
+insert ( 10258 434 1114 1082 2 s 2372 403 0 )
+insert ( 10259 434 1114 1082 3 s 2373 403 0 )
+insert ( 10260 434 1114 1082 4 s 2374 403 0 )
+insert ( 10261 434 1114 1082 5 s 2375 403 0 )
+insert ( 10262 434 1114 1184 1 s 2534 403 0 )
+insert ( 10263 434 1114 1184 2 s 2535 403 0 )
+insert ( 10264 434 1114 1184 3 s 2536 403 0 )
+insert ( 10265 434 1114 1184 4 s 2537 403 0 )
+insert ( 10266 434 1114 1184 5 s 2538 403 0 )
+insert ( 10267 434 1184 1184 1 s 1322 403 0 )
+insert ( 10268 434 1184 1184 2 s 1323 403 0 )
+insert ( 10269 434 1184 1184 3 s 1320 403 0 )
+insert ( 10270 434 1184 1184 4 s 1325 403 0 )
+insert ( 10271 434 1184 1184 5 s 1324 403 0 )
+insert ( 10272 434 1184 1082 1 s 2384 403 0 )
+insert ( 10273 434 1184 1082 2 s 2385 403 0 )
+insert ( 10274 434 1184 1082 3 s 2386 403 0 )
+insert ( 10275 434 1184 1082 4 s 2387 403 0 )
+insert ( 10276 434 1184 1082 5 s 2388 403 0 )
+insert ( 10277 434 1184 1114 1 s 2540 403 0 )
+insert ( 10278 434 1184 1114 2 s 2541 403 0 )
+insert ( 10279 434 1184 1114 3 s 2542 403 0 )
+insert ( 10280 434 1184 1114 4 s 2543 403 0 )
+insert ( 10281 434 1184 1114 5 s 2544 403 0 )
+insert ( 10282 1996 1083 1083 1 s 1110 403 0 )
+insert ( 10283 1996 1083 1083 2 s 1111 403 0 )
+insert ( 10284 1996 1083 1083 3 s 1108 403 0 )
+insert ( 10285 1996 1083 1083 4 s 1113 403 0 )
+insert ( 10286 1996 1083 1083 5 s 1112 403 0 )
+insert ( 10287 2000 1266 1266 1 s 1552 403 0 )
+insert ( 10288 2000 1266 1266 2 s 1553 403 0 )
+insert ( 10289 2000 1266 1266 3 s 1550 403 0 )
+insert ( 10290 2000 1266 1266 4 s 1555 403 0 )
+insert ( 10291 2000 1266 1266 5 s 1554 403 0 )
+insert ( 10292 1982 1186 1186 1 s 1332 403 0 )
+insert ( 10293 1982 1186 1186 2 s 1333 403 0 )
+insert ( 10294 1982 1186 1186 3 s 1330 403 0 )
+insert ( 10295 1982 1186 1186 4 s 1335 403 0 )
+insert ( 10296 1982 1186 1186 5 s 1334 403 0 )
+insert ( 10297 1984 829 829 1 s 1222 403 0 )
+insert ( 10298 1984 829 829 2 s 1223 403 0 )
+insert ( 10299 1984 829 829 3 s 1220 403 0 )
+insert ( 10300 1984 829 829 4 s 1225 403 0 )
+insert ( 10301 1984 829 829 5 s 1224 403 0 )
+insert ( 10302 3371 774 774 1 s 3364 403 0 )
+insert ( 10303 3371 774 774 2 s 3365 403 0 )
+insert ( 10304 3371 774 774 3 s 3362 403 0 )
+insert ( 10305 3371 774 774 4 s 3367 403 0 )
+insert ( 10306 3371 774 774 5 s 3366 403 0 )
+insert ( 10307 1974 869 869 1 s 1203 403 0 )
+insert ( 10308 1974 869 869 2 s 1204 403 0 )
+insert ( 10309 1974 869 869 3 s 1201 403 0 )
+insert ( 10310 1974 869 869 4 s 1206 403 0 )
+insert ( 10311 1974 869 869 5 s 1205 403 0 )
+insert ( 10312 1988 1700 1700 1 s 1754 403 0 )
+insert ( 10313 1988 1700 1700 2 s 1755 403 0 )
+insert ( 10314 1988 1700 1700 3 s 1752 403 0 )
+insert ( 10315 1988 1700 1700 4 s 1757 403 0 )
+insert ( 10316 1988 1700 1700 5 s 1756 403 0 )
+insert ( 10317 424 16 16 1 s 58 403 0 )
+insert ( 10318 424 16 16 2 s 1694 403 0 )
+insert ( 10319 424 16 16 3 s 91 403 0 )
+insert ( 10320 424 16 16 4 s 1695 403 0 )
+insert ( 10321 424 16 16 5 s 59 403 0 )
+insert ( 10322 423 1560 1560 1 s 1786 403 0 )
+insert ( 10323 423 1560 1560 2 s 1788 403 0 )
+insert ( 10324 423 1560 1560 3 s 1784 403 0 )
+insert ( 10325 423 1560 1560 4 s 1789 403 0 )
+insert ( 10326 423 1560 1560 5 s 1787 403 0 )
+insert ( 10327 2002 1562 1562 1 s 1806 403 0 )
+insert ( 10328 2002 1562 1562 2 s 1808 403 0 )
+insert ( 10329 2002 1562 1562 3 s 1804 403 0 )
+insert ( 10330 2002 1562 1562 4 s 1809 403 0 )
+insert ( 10331 2002 1562 1562 5 s 1807 403 0 )
+insert ( 10332 2095 25 25 1 s 2314 403 0 )
+insert ( 10333 2095 25 25 2 s 2315 403 0 )
+insert ( 10334 2095 25 25 3 s 98 403 0 )
+insert ( 10335 2095 25 25 4 s 2317 403 0 )
+insert ( 10336 2095 25 25 5 s 2318 403 0 )
+insert ( 10337 2097 1042 1042 1 s 2326 403 0 )
+insert ( 10338 2097 1042 1042 2 s 2327 403 0 )
+insert ( 10339 2097 1042 1042 3 s 1054 403 0 )
+insert ( 10340 2097 1042 1042 4 s 2329 403 0 )
+insert ( 10341 2097 1042 1042 5 s 2330 403 0 )
+insert ( 10342 2099 790 790 1 s 902 403 0 )
+insert ( 10343 2099 790 790 2 s 904 403 0 )
+insert ( 10344 2099 790 790 3 s 900 403 0 )
+insert ( 10345 2099 790 790 4 s 905 403 0 )
+insert ( 10346 2099 790 790 5 s 903 403 0 )
+insert ( 10347 397 2277 2277 1 s 1072 403 0 )
+insert ( 10348 397 2277 2277 2 s 1074 403 0 )
+insert ( 10349 397 2277 2277 3 s 1070 403 0 )
+insert ( 10350 397 2277 2277 4 s 1075 403 0 )
+insert ( 10351 397 2277 2277 5 s 1073 403 0 )
+insert ( 10352 2994 2249 2249 1 s 2990 403 0 )
+insert ( 10353 2994 2249 2249 2 s 2992 403 0 )
+insert ( 10354 2994 2249 2249 3 s 2988 403 0 )
+insert ( 10355 2994 2249 2249 4 s 2993 403 0 )
+insert ( 10356 2994 2249 2249 5 s 2991 403 0 )
+insert ( 10357 3194 2249 2249 1 s 3190 403 0 )
+insert ( 10358 3194 2249 2249 2 s 3192 403 0 )
+insert ( 10359 3194 2249 2249 3 s 3188 403 0 )
+insert ( 10360 3194 2249 2249 4 s 3193 403 0 )
+insert ( 10361 3194 2249 2249 5 s 3191 403 0 )
+insert ( 10362 2968 2950 2950 1 s 2974 403 0 )
+insert ( 10363 2968 2950 2950 2 s 2976 403 0 )
+insert ( 10364 2968 2950 2950 3 s 2972 403 0 )
+insert ( 10365 2968 2950 2950 4 s 2977 403 0 )
+insert ( 10366 2968 2950 2950 5 s 2975 403 0 )
+insert ( 10367 3253 3220 3220 1 s 3224 403 0 )
+insert ( 10368 3253 3220 3220 2 s 3226 403 0 )
+insert ( 10369 3253 3220 3220 3 s 3222 403 0 )
+insert ( 10370 3253 3220 3220 4 s 3227 403 0 )
+insert ( 10371 3253 3220 3220 5 s 3225 403 0 )
+insert ( 10372 427 1042 1042 1 s 1054 405 0 )
+insert ( 10373 431 18 18 1 s 92 405 0 )
+insert ( 10374 435 1082 1082 1 s 1093 405 0 )
+insert ( 10375 1971 700 700 1 s 620 405 0 )
+insert ( 10376 1971 701 701 1 s 670 405 0 )
+insert ( 10377 1971 700 701 1 s 1120 405 0 )
+insert ( 10378 1971 701 700 1 s 1130 405 0 )
+insert ( 10379 1975 869 869 1 s 1201 405 0 )
+insert ( 10380 1977 21 21 1 s 94 405 0 )
+insert ( 10381 1977 23 23 1 s 96 405 0 )
+insert ( 10382 1977 20 20 1 s 410 405 0 )
+insert ( 10383 1977 21 23 1 s 532 405 0 )
+insert ( 10384 1977 21 20 1 s 1862 405 0 )
+insert ( 10385 1977 23 21 1 s 533 405 0 )
+insert ( 10386 1977 23 20 1 s 15 405 0 )
+insert ( 10387 1977 20 21 1 s 1868 405 0 )
+insert ( 10388 1977 20 23 1 s 416 405 0 )
+insert ( 10389 1983 1186 1186 1 s 1330 405 0 )
+insert ( 10390 1985 829 829 1 s 1220 405 0 )
+insert ( 10391 3372 774 774 1 s 3362 405 0 )
+insert ( 10392 1990 26 26 1 s 607 405 0 )
+insert ( 10393 1992 30 30 1 s 649 405 0 )
+insert ( 10394 1995 25 25 1 s 98 405 0 )
+insert ( 10395 1995 19 19 1 s 93 405 0 )
+insert ( 10396 1995 19 25 1 s 254 405 0 )
+insert ( 10397 1995 25 19 1 s 260 405 0 )
+insert ( 10398 1997 1083 1083 1 s 1108 405 0 )
+insert ( 10399 1999 1184 1184 1 s 1320 405 0 )
+insert ( 10400 2001 1266 1266 1 s 1550 405 0 )
+insert ( 10401 2040 1114 1114 1 s 2060 405 0 )
+insert ( 10402 2222 16 16 1 s 91 405 0 )
+insert ( 10403 2223 17 17 1 s 1955 405 0 )
+insert ( 10404 2225 28 28 1 s 352 405 0 )
+insert ( 10405 5032 5069 5069 1 s 5068 405 0 )
+insert ( 10406 2226 29 29 1 s 385 405 0 )
+insert ( 10407 2227 27 27 1 s 387 405 0 )
+insert ( 10408 2229 25 25 1 s 98 405 0 )
+insert ( 10409 2231 1042 1042 1 s 1054 405 0 )
+insert ( 10410 2235 1033 1033 1 s 974 405 0 )
+insert ( 10411 2969 2950 2950 1 s 2972 405 0 )
+insert ( 10412 3254 3220 3220 1 s 3222 405 0 )
+insert ( 10413 1998 1700 1700 1 s 1752 405 0 )
+insert ( 10414 627 2277 2277 1 s 1070 405 0 )
+insert ( 10415 2593 603 603 1 s 493 783 0 )
+insert ( 10416 2593 603 603 2 s 494 783 0 )
+insert ( 10417 2593 603 603 3 s 500 783 0 )
+insert ( 10418 2593 603 603 4 s 495 783 0 )
+insert ( 10419 2593 603 603 5 s 496 783 0 )
+insert ( 10420 2593 603 603 6 s 499 783 0 )
+insert ( 10421 2593 603 603 7 s 498 783 0 )
+insert ( 10422 2593 603 603 8 s 497 783 0 )
+insert ( 10423 2593 603 603 9 s 2571 783 0 )
+insert ( 10424 2593 603 603 10 s 2570 783 0 )
+insert ( 10425 2593 603 603 11 s 2573 783 0 )
+insert ( 10426 2593 603 603 12 s 2572 783 0 )
+insert ( 10427 2593 603 603 13 s 2863 783 0 )
+insert ( 10428 2593 603 603 14 s 2862 783 0 )
+insert ( 10429 2593 603 600 15 o 606 783 1970 )
+insert ( 10430 1029 600 600 11 s 506 783 0 )
+insert ( 10431 1029 600 600 1 s 507 783 0 )
+insert ( 10432 1029 600 600 5 s 508 783 0 )
+insert ( 10433 1029 600 600 10 s 509 783 0 )
+insert ( 10434 1029 600 600 6 s 510 783 0 )
+insert ( 10435 1029 600 600 15 o 517 783 1970 )
+insert ( 10436 1029 600 603 28 s 511 783 0 )
+insert ( 10437 1029 600 604 48 s 756 783 0 )
+insert ( 10438 1029 600 718 68 s 758 783 0 )
+insert ( 10439 2594 604 604 1 s 485 783 0 )
+insert ( 10440 2594 604 604 2 s 486 783 0 )
+insert ( 10441 2594 604 604 3 s 492 783 0 )
+insert ( 10442 2594 604 604 4 s 487 783 0 )
+insert ( 10443 2594 604 604 5 s 488 783 0 )
+insert ( 10444 2594 604 604 6 s 491 783 0 )
+insert ( 10445 2594 604 604 7 s 490 783 0 )
+insert ( 10446 2594 604 604 8 s 489 783 0 )
+insert ( 10447 2594 604 604 9 s 2575 783 0 )
+insert ( 10448 2594 604 604 10 s 2574 783 0 )
+insert ( 10449 2594 604 604 11 s 2577 783 0 )
+insert ( 10450 2594 604 604 12 s 2576 783 0 )
+insert ( 10451 2594 604 604 13 s 2861 783 0 )
+insert ( 10452 2594 604 604 14 s 2860 783 0 )
+insert ( 10453 2594 604 600 15 o 3289 783 1970 )
+insert ( 10454 2595 718 718 1 s 1506 783 0 )
+insert ( 10455 2595 718 718 2 s 1507 783 0 )
+insert ( 10456 2595 718 718 3 s 1513 783 0 )
+insert ( 10457 2595 718 718 4 s 1508 783 0 )
+insert ( 10458 2595 718 718 5 s 1509 783 0 )
+insert ( 10459 2595 718 718 6 s 1512 783 0 )
+insert ( 10460 2595 718 718 7 s 1511 783 0 )
+insert ( 10461 2595 718 718 8 s 1510 783 0 )
+insert ( 10462 2595 718 718 9 s 2589 783 0 )
+insert ( 10463 2595 718 718 10 s 1515 783 0 )
+insert ( 10464 2595 718 718 11 s 1514 783 0 )
+insert ( 10465 2595 718 718 12 s 2590 783 0 )
+insert ( 10466 2595 718 718 13 s 2865 783 0 )
+insert ( 10467 2595 718 718 14 s 2864 783 0 )
+insert ( 10468 2595 718 600 15 o 3291 783 1970 )
+insert ( 10469 2745 2277 2277 1 s 2750 2742 0 )
+insert ( 10470 2745 2277 2277 2 s 2751 2742 0 )
+insert ( 10471 2745 2277 2277 3 s 2752 2742 0 )
+insert ( 10472 2745 2277 2277 4 s 1070 2742 0 )
+insert ( 10473 3522 3500 3500 1 s 3518 403 0 )
+insert ( 10474 3522 3500 3500 2 s 3520 403 0 )
+insert ( 10475 3522 3500 3500 3 s 3516 403 0 )
+insert ( 10476 3522 3500 3500 4 s 3521 403 0 )
+insert ( 10477 3522 3500 3500 5 s 3519 403 0 )
+insert ( 10478 3523 3500 3500 1 s 3516 405 0 )
+insert ( 10479 3626 3614 3614 1 s 3627 403 0 )
+insert ( 10480 3626 3614 3614 2 s 3628 403 0 )
+insert ( 10481 3626 3614 3614 3 s 3629 403 0 )
+insert ( 10482 3626 3614 3614 4 s 3631 403 0 )
+insert ( 10483 3626 3614 3614 5 s 3632 403 0 )
+insert ( 10484 3655 3614 3615 1 s 3636 783 0 )
+insert ( 10485 3659 3614 3615 1 s 3636 2742 0 )
+insert ( 10486 3659 3614 3615 2 s 3660 2742 0 )
+insert ( 10487 3683 3615 3615 1 s 3674 403 0 )
+insert ( 10488 3683 3615 3615 2 s 3675 403 0 )
+insert ( 10489 3683 3615 3615 3 s 3676 403 0 )
+insert ( 10490 3683 3615 3615 4 s 3678 403 0 )
+insert ( 10491 3683 3615 3615 5 s 3679 403 0 )
+insert ( 10492 3702 3615 3615 7 s 3693 783 0 )
+insert ( 10493 3702 3615 3615 8 s 3694 783 0 )
+insert ( 10494 3901 3831 3831 1 s 3884 403 0 )
+insert ( 10495 3901 3831 3831 2 s 3885 403 0 )
+insert ( 10496 3901 3831 3831 3 s 3882 403 0 )
+insert ( 10497 3901 3831 3831 4 s 3886 403 0 )
+insert ( 10498 3901 3831 3831 5 s 3887 403 0 )
+insert ( 10499 3903 3831 3831 1 s 3882 405 0 )
+insert ( 10500 3919 3831 3831 1 s 3893 783 0 )
+insert ( 10501 3919 3831 3831 2 s 3895 783 0 )
+insert ( 10502 3919 3831 3831 3 s 3888 783 0 )
+insert ( 10503 3919 3831 3831 4 s 3896 783 0 )
+insert ( 10504 3919 3831 3831 5 s 3894 783 0 )
+insert ( 10505 3919 3831 3831 6 s 3897 783 0 )
+insert ( 10506 3919 3831 3831 7 s 3890 783 0 )
+insert ( 10507 3919 3831 3831 8 s 3892 783 0 )
+insert ( 10508 3919 3831 2283 16 s 3889 783 0 )
+insert ( 10509 3919 3831 3831 18 s 3882 783 0 )
+insert ( 10510 4015 600 600 11 s 506 4000 0 )
+insert ( 10511 4015 600 600 1 s 507 4000 0 )
+insert ( 10512 4015 600 600 5 s 508 4000 0 )
+insert ( 10513 4015 600 600 10 s 509 4000 0 )
+insert ( 10514 4015 600 600 6 s 510 4000 0 )
+insert ( 10515 4015 600 603 8 s 511 4000 0 )
+insert ( 10516 4015 600 600 15 o 517 4000 1970 )
+insert ( 10517 4016 600 600 11 s 506 4000 0 )
+insert ( 10518 4016 600 600 1 s 507 4000 0 )
+insert ( 10519 4016 600 600 5 s 508 4000 0 )
+insert ( 10520 4016 600 600 10 s 509 4000 0 )
+insert ( 10521 4016 600 600 6 s 510 4000 0 )
+insert ( 10522 4016 600 603 8 s 511 4000 0 )
+insert ( 10523 4016 600 600 15 o 517 4000 1970 )
+insert ( 10524 4017 25 25 1 s 2314 4000 0 )
+insert ( 10525 4017 25 25 2 s 2315 4000 0 )
+insert ( 10526 4017 25 25 3 s 98 4000 0 )
+insert ( 10527 4017 25 25 4 s 2317 4000 0 )
+insert ( 10528 4017 25 25 5 s 2318 4000 0 )
+insert ( 10529 4017 25 25 11 s 664 4000 0 )
+insert ( 10530 4017 25 25 12 s 665 4000 0 )
+insert ( 10531 4017 25 25 14 s 667 4000 0 )
+insert ( 10532 4017 25 25 15 s 666 4000 0 )
+insert ( 10533 4017 25 25 28 s 3877 4000 0 )
+insert ( 10534 4033 3802 3802 1 s 3242 403 0 )
+insert ( 10535 4033 3802 3802 2 s 3244 403 0 )
+insert ( 10536 4033 3802 3802 3 s 3240 403 0 )
+insert ( 10537 4033 3802 3802 4 s 3245 403 0 )
+insert ( 10538 4033 3802 3802 5 s 3243 403 0 )
+insert ( 10539 4034 3802 3802 1 s 3240 405 0 )
+insert ( 10540 4036 3802 3802 7 s 3246 2742 0 )
+insert ( 10541 4036 3802 25 9 s 3247 2742 0 )
+insert ( 10542 4036 3802 1009 10 s 3248 2742 0 )
+insert ( 10543 4036 3802 1009 11 s 3249 2742 0 )
+insert ( 10544 4036 3802 4072 15 s 4012 2742 0 )
+insert ( 10545 4036 3802 4072 16 s 4013 2742 0 )
+insert ( 10546 4037 3802 3802 7 s 3246 2742 0 )
+insert ( 10547 4037 3802 4072 15 s 4012 2742 0 )
+insert ( 10548 4037 3802 4072 16 s 4013 2742 0 )
+insert ( 10549 3474 3831 3831 1 s 3893 4000 0 )
+insert ( 10550 3474 3831 3831 2 s 3895 4000 0 )
+insert ( 10551 3474 3831 3831 3 s 3888 4000 0 )
+insert ( 10552 3474 3831 3831 4 s 3896 4000 0 )
+insert ( 10553 3474 3831 3831 5 s 3894 4000 0 )
+insert ( 10554 3474 3831 3831 6 s 3897 4000 0 )
+insert ( 10555 3474 3831 3831 7 s 3890 4000 0 )
+insert ( 10556 3474 3831 3831 8 s 3892 4000 0 )
+insert ( 10557 3474 3831 2283 16 s 3889 4000 0 )
+insert ( 10558 3474 3831 3831 18 s 3882 4000 0 )
+insert ( 10559 5000 603 603 1 s 493 4000 0 )
+insert ( 10560 5000 603 603 2 s 494 4000 0 )
+insert ( 10561 5000 603 603 3 s 500 4000 0 )
+insert ( 10562 5000 603 603 4 s 495 4000 0 )
+insert ( 10563 5000 603 603 5 s 496 4000 0 )
+insert ( 10564 5000 603 603 6 s 499 4000 0 )
+insert ( 10565 5000 603 603 7 s 498 4000 0 )
+insert ( 10566 5000 603 603 8 s 497 4000 0 )
+insert ( 10567 5000 603 603 9 s 2571 4000 0 )
+insert ( 10568 5000 603 603 10 s 2570 4000 0 )
+insert ( 10569 5000 603 603 11 s 2573 4000 0 )
+insert ( 10570 5000 603 603 12 s 2572 4000 0 )
+insert ( 10571 5000 603 600 15 o 606 4000 1970 )
+insert ( 10572 5008 604 604 1 s 485 4000 0 )
+insert ( 10573 5008 604 604 2 s 486 4000 0 )
+insert ( 10574 5008 604 604 3 s 492 4000 0 )
+insert ( 10575 5008 604 604 4 s 487 4000 0 )
+insert ( 10576 5008 604 604 5 s 488 4000 0 )
+insert ( 10577 5008 604 604 6 s 491 4000 0 )
+insert ( 10578 5008 604 604 7 s 490 4000 0 )
+insert ( 10579 5008 604 604 8 s 489 4000 0 )
+insert ( 10580 5008 604 604 9 s 2575 4000 0 )
+insert ( 10581 5008 604 604 10 s 2574 4000 0 )
+insert ( 10582 5008 604 604 11 s 2577 4000 0 )
+insert ( 10583 5008 604 604 12 s 2576 4000 0 )
+insert ( 10584 5008 604 600 15 o 3289 4000 1970 )
+insert ( 10585 3550 869 869 3 s 3552 783 0 )
+insert ( 10586 3550 869 869 18 s 1201 783 0 )
+insert ( 10587 3550 869 869 19 s 1202 783 0 )
+insert ( 10588 3550 869 869 20 s 1203 783 0 )
+insert ( 10589 3550 869 869 21 s 1204 783 0 )
+insert ( 10590 3550 869 869 22 s 1205 783 0 )
+insert ( 10591 3550 869 869 23 s 1206 783 0 )
+insert ( 10592 3550 869 869 24 s 931 783 0 )
+insert ( 10593 3550 869 869 25 s 932 783 0 )
+insert ( 10594 3550 869 869 26 s 933 783 0 )
+insert ( 10595 3550 869 869 27 s 934 783 0 )
+insert ( 10596 3794 869 869 3 s 3552 4000 0 )
+insert ( 10597 3794 869 869 18 s 1201 4000 0 )
+insert ( 10598 3794 869 869 19 s 1202 4000 0 )
+insert ( 10599 3794 869 869 20 s 1203 4000 0 )
+insert ( 10600 3794 869 869 21 s 1204 4000 0 )
+insert ( 10601 3794 869 869 22 s 1205 4000 0 )
+insert ( 10602 3794 869 869 23 s 1206 4000 0 )
+insert ( 10603 3794 869 869 24 s 931 4000 0 )
+insert ( 10604 3794 869 869 25 s 932 4000 0 )
+insert ( 10605 3794 869 869 26 s 933 4000 0 )
+insert ( 10606 3794 869 869 27 s 934 4000 0 )
+insert ( 10607 4064 17 17 1 s 1957 3580 0 )
+insert ( 10608 4064 17 17 2 s 1958 3580 0 )
+insert ( 10609 4064 17 17 3 s 1955 3580 0 )
+insert ( 10610 4064 17 17 4 s 1960 3580 0 )
+insert ( 10611 4064 17 17 5 s 1959 3580 0 )
+insert ( 10612 4062 18 18 1 s 631 3580 0 )
+insert ( 10613 4062 18 18 2 s 632 3580 0 )
+insert ( 10614 4062 18 18 3 s 92 3580 0 )
+insert ( 10615 4062 18 18 4 s 634 3580 0 )
+insert ( 10616 4062 18 18 5 s 633 3580 0 )
+insert ( 10617 4065 19 19 1 s 660 3580 0 )
+insert ( 10618 4065 19 19 2 s 661 3580 0 )
+insert ( 10619 4065 19 19 3 s 93 3580 0 )
+insert ( 10620 4065 19 19 4 s 663 3580 0 )
+insert ( 10621 4065 19 19 5 s 662 3580 0 )
+insert ( 10622 4054 20 20 1 s 412 3580 0 )
+insert ( 10623 4054 20 20 2 s 414 3580 0 )
+insert ( 10624 4054 20 20 3 s 410 3580 0 )
+insert ( 10625 4054 20 20 4 s 415 3580 0 )
+insert ( 10626 4054 20 20 5 s 413 3580 0 )
+insert ( 10627 4054 20 21 1 s 1870 3580 0 )
+insert ( 10628 4054 20 21 2 s 1872 3580 0 )
+insert ( 10629 4054 20 21 3 s 1868 3580 0 )
+insert ( 10630 4054 20 21 4 s 1873 3580 0 )
+insert ( 10631 4054 20 21 5 s 1871 3580 0 )
+insert ( 10632 4054 20 23 1 s 418 3580 0 )
+insert ( 10633 4054 20 23 2 s 420 3580 0 )
+insert ( 10634 4054 20 23 3 s 416 3580 0 )
+insert ( 10635 4054 20 23 4 s 430 3580 0 )
+insert ( 10636 4054 20 23 5 s 419 3580 0 )
+insert ( 10637 4054 21 21 1 s 95 3580 0 )
+insert ( 10638 4054 21 21 2 s 522 3580 0 )
+insert ( 10639 4054 21 21 3 s 94 3580 0 )
+insert ( 10640 4054 21 21 4 s 524 3580 0 )
+insert ( 10641 4054 21 21 5 s 520 3580 0 )
+insert ( 10642 4054 21 20 1 s 1864 3580 0 )
+insert ( 10643 4054 21 20 2 s 1866 3580 0 )
+insert ( 10644 4054 21 20 3 s 1862 3580 0 )
+insert ( 10645 4054 21 20 4 s 1867 3580 0 )
+insert ( 10646 4054 21 20 5 s 1865 3580 0 )
+insert ( 10647 4054 21 23 1 s 534 3580 0 )
+insert ( 10648 4054 21 23 2 s 540 3580 0 )
+insert ( 10649 4054 21 23 3 s 532 3580 0 )
+insert ( 10650 4054 21 23 4 s 542 3580 0 )
+insert ( 10651 4054 21 23 5 s 536 3580 0 )
+insert ( 10652 4054 23 23 1 s 97 3580 0 )
+insert ( 10653 4054 23 23 2 s 523 3580 0 )
+insert ( 10654 4054 23 23 3 s 96 3580 0 )
+insert ( 10655 4054 23 23 4 s 525 3580 0 )
+insert ( 10656 4054 23 23 5 s 521 3580 0 )
+insert ( 10657 4054 23 21 1 s 535 3580 0 )
+insert ( 10658 4054 23 21 2 s 541 3580 0 )
+insert ( 10659 4054 23 21 3 s 533 3580 0 )
+insert ( 10660 4054 23 21 4 s 543 3580 0 )
+insert ( 10661 4054 23 21 5 s 537 3580 0 )
+insert ( 10662 4054 23 20 1 s 37 3580 0 )
+insert ( 10663 4054 23 20 2 s 80 3580 0 )
+insert ( 10664 4054 23 20 3 s 15 3580 0 )
+insert ( 10665 4054 23 20 4 s 82 3580 0 )
+insert ( 10666 4054 23 20 5 s 76 3580 0 )
+insert ( 10667 4056 25 25 1 s 664 3580 0 )
+insert ( 10668 4056 25 25 2 s 665 3580 0 )
+insert ( 10669 4056 25 25 3 s 98 3580 0 )
+insert ( 10670 4056 25 25 4 s 667 3580 0 )
+insert ( 10671 4056 25 25 5 s 666 3580 0 )
+insert ( 10672 4068 26 26 1 s 609 3580 0 )
+insert ( 10673 4068 26 26 2 s 611 3580 0 )
+insert ( 10674 4068 26 26 3 s 607 3580 0 )
+insert ( 10675 4068 26 26 4 s 612 3580 0 )
+insert ( 10676 4068 26 26 5 s 610 3580 0 )
+insert ( 10677 4069 27 27 1 s 2799 3580 0 )
+insert ( 10678 4069 27 27 2 s 2801 3580 0 )
+insert ( 10679 4069 27 27 3 s 387 3580 0 )
+insert ( 10680 4069 27 27 4 s 2802 3580 0 )
+insert ( 10681 4069 27 27 5 s 2800 3580 0 )
+insert ( 10682 4070 700 700 1 s 622 3580 0 )
+insert ( 10683 4070 700 700 2 s 624 3580 0 )
+insert ( 10684 4070 700 700 3 s 620 3580 0 )
+insert ( 10685 4070 700 700 4 s 625 3580 0 )
+insert ( 10686 4070 700 700 5 s 623 3580 0 )
+insert ( 10687 4070 700 701 1 s 1122 3580 0 )
+insert ( 10688 4070 700 701 2 s 1124 3580 0 )
+insert ( 10689 4070 700 701 3 s 1120 3580 0 )
+insert ( 10690 4070 700 701 4 s 1125 3580 0 )
+insert ( 10691 4070 700 701 5 s 1123 3580 0 )
+insert ( 10692 4070 701 700 1 s 1132 3580 0 )
+insert ( 10693 4070 701 700 2 s 1134 3580 0 )
+insert ( 10694 4070 701 700 3 s 1130 3580 0 )
+insert ( 10695 4070 701 700 4 s 1135 3580 0 )
+insert ( 10696 4070 701 700 5 s 1133 3580 0 )
+insert ( 10697 4070 701 701 1 s 672 3580 0 )
+insert ( 10698 4070 701 701 2 s 673 3580 0 )
+insert ( 10699 4070 701 701 3 s 670 3580 0 )
+insert ( 10700 4070 701 701 4 s 675 3580 0 )
+insert ( 10701 4070 701 701 5 s 674 3580 0 )
+insert ( 10702 4074 829 829 1 s 1222 3580 0 )
+insert ( 10703 4074 829 829 2 s 1223 3580 0 )
+insert ( 10704 4074 829 829 3 s 1220 3580 0 )
+insert ( 10705 4074 829 829 4 s 1225 3580 0 )
+insert ( 10706 4074 829 829 5 s 1224 3580 0 )
+insert ( 10707 4109 774 774 1 s 3364 3580 0 )
+insert ( 10708 4109 774 774 2 s 3365 3580 0 )
+insert ( 10709 4109 774 774 3 s 3362 3580 0 )
+insert ( 10710 4109 774 774 4 s 3367 3580 0 )
+insert ( 10711 4109 774 774 5 s 3366 3580 0 )
+insert ( 10712 4075 869 869 1 s 1203 3580 0 )
+insert ( 10713 4075 869 869 2 s 1204 3580 0 )
+insert ( 10714 4075 869 869 3 s 1201 3580 0 )
+insert ( 10715 4075 869 869 4 s 1206 3580 0 )
+insert ( 10716 4075 869 869 5 s 1205 3580 0 )
+insert ( 10717 4102 869 869 3 s 3552 3580 0 )
+insert ( 10718 4102 869 869 7 s 934 3580 0 )
+insert ( 10719 4102 869 869 8 s 932 3580 0 )
+insert ( 10720 4102 869 869 18 s 1201 3580 0 )
+insert ( 10721 4102 869 869 24 s 933 3580 0 )
+insert ( 10722 4102 869 869 26 s 931 3580 0 )
+insert ( 10723 4076 1042 1042 1 s 1058 3580 0 )
+insert ( 10724 4076 1042 1042 2 s 1059 3580 0 )
+insert ( 10725 4076 1042 1042 3 s 1054 3580 0 )
+insert ( 10726 4076 1042 1042 4 s 1061 3580 0 )
+insert ( 10727 4076 1042 1042 5 s 1060 3580 0 )
+insert ( 10728 4077 1083 1083 1 s 1110 3580 0 )
+insert ( 10729 4077 1083 1083 2 s 1111 3580 0 )
+insert ( 10730 4077 1083 1083 3 s 1108 3580 0 )
+insert ( 10731 4077 1083 1083 4 s 1113 3580 0 )
+insert ( 10732 4077 1083 1083 5 s 1112 3580 0 )
+insert ( 10733 4059 1114 1114 1 s 2062 3580 0 )
+insert ( 10734 4059 1114 1114 2 s 2063 3580 0 )
+insert ( 10735 4059 1114 1114 3 s 2060 3580 0 )
+insert ( 10736 4059 1114 1114 4 s 2065 3580 0 )
+insert ( 10737 4059 1114 1114 5 s 2064 3580 0 )
+insert ( 10738 4059 1114 1082 1 s 2371 3580 0 )
+insert ( 10739 4059 1114 1082 2 s 2372 3580 0 )
+insert ( 10740 4059 1114 1082 3 s 2373 3580 0 )
+insert ( 10741 4059 1114 1082 4 s 2374 3580 0 )
+insert ( 10742 4059 1114 1082 5 s 2375 3580 0 )
+insert ( 10743 4059 1114 1184 1 s 2534 3580 0 )
+insert ( 10744 4059 1114 1184 2 s 2535 3580 0 )
+insert ( 10745 4059 1114 1184 3 s 2536 3580 0 )
+insert ( 10746 4059 1114 1184 4 s 2537 3580 0 )
+insert ( 10747 4059 1114 1184 5 s 2538 3580 0 )
+insert ( 10748 4059 1082 1082 1 s 1095 3580 0 )
+insert ( 10749 4059 1082 1082 2 s 1096 3580 0 )
+insert ( 10750 4059 1082 1082 3 s 1093 3580 0 )
+insert ( 10751 4059 1082 1082 4 s 1098 3580 0 )
+insert ( 10752 4059 1082 1082 5 s 1097 3580 0 )
+insert ( 10753 4059 1082 1114 1 s 2345 3580 0 )
+insert ( 10754 4059 1082 1114 2 s 2346 3580 0 )
+insert ( 10755 4059 1082 1114 3 s 2347 3580 0 )
+insert ( 10756 4059 1082 1114 4 s 2348 3580 0 )
+insert ( 10757 4059 1082 1114 5 s 2349 3580 0 )
+insert ( 10758 4059 1082 1184 1 s 2358 3580 0 )
+insert ( 10759 4059 1082 1184 2 s 2359 3580 0 )
+insert ( 10760 4059 1082 1184 3 s 2360 3580 0 )
+insert ( 10761 4059 1082 1184 4 s 2361 3580 0 )
+insert ( 10762 4059 1082 1184 5 s 2362 3580 0 )
+insert ( 10763 4059 1184 1082 1 s 2384 3580 0 )
+insert ( 10764 4059 1184 1082 2 s 2385 3580 0 )
+insert ( 10765 4059 1184 1082 3 s 2386 3580 0 )
+insert ( 10766 4059 1184 1082 4 s 2387 3580 0 )
+insert ( 10767 4059 1184 1082 5 s 2388 3580 0 )
+insert ( 10768 4059 1184 1114 1 s 2540 3580 0 )
+insert ( 10769 4059 1184 1114 2 s 2541 3580 0 )
+insert ( 10770 4059 1184 1114 3 s 2542 3580 0 )
+insert ( 10771 4059 1184 1114 4 s 2543 3580 0 )
+insert ( 10772 4059 1184 1114 5 s 2544 3580 0 )
+insert ( 10773 4059 1184 1184 1 s 1322 3580 0 )
+insert ( 10774 4059 1184 1184 2 s 1323 3580 0 )
+insert ( 10775 4059 1184 1184 3 s 1320 3580 0 )
+insert ( 10776 4059 1184 1184 4 s 1325 3580 0 )
+insert ( 10777 4059 1184 1184 5 s 1324 3580 0 )
+insert ( 10778 4078 1186 1186 1 s 1332 3580 0 )
+insert ( 10779 4078 1186 1186 2 s 1333 3580 0 )
+insert ( 10780 4078 1186 1186 3 s 1330 3580 0 )
+insert ( 10781 4078 1186 1186 4 s 1335 3580 0 )
+insert ( 10782 4078 1186 1186 5 s 1334 3580 0 )
+insert ( 10783 4058 1266 1266 1 s 1552 3580 0 )
+insert ( 10784 4058 1266 1266 2 s 1553 3580 0 )
+insert ( 10785 4058 1266 1266 3 s 1550 3580 0 )
+insert ( 10786 4058 1266 1266 4 s 1555 3580 0 )
+insert ( 10787 4058 1266 1266 5 s 1554 3580 0 )
+insert ( 10788 4079 1560 1560 1 s 1786 3580 0 )
+insert ( 10789 4079 1560 1560 2 s 1788 3580 0 )
+insert ( 10790 4079 1560 1560 3 s 1784 3580 0 )
+insert ( 10791 4079 1560 1560 4 s 1789 3580 0 )
+insert ( 10792 4079 1560 1560 5 s 1787 3580 0 )
+insert ( 10793 4080 1562 1562 1 s 1806 3580 0 )
+insert ( 10794 4080 1562 1562 2 s 1808 3580 0 )
+insert ( 10795 4080 1562 1562 3 s 1804 3580 0 )
+insert ( 10796 4080 1562 1562 4 s 1809 3580 0 )
+insert ( 10797 4080 1562 1562 5 s 1807 3580 0 )
+insert ( 10798 4055 1700 1700 1 s 1754 3580 0 )
+insert ( 10799 4055 1700 1700 2 s 1755 3580 0 )
+insert ( 10800 4055 1700 1700 3 s 1752 3580 0 )
+insert ( 10801 4055 1700 1700 4 s 1757 3580 0 )
+insert ( 10802 4055 1700 1700 5 s 1756 3580 0 )
+insert ( 10803 4081 2950 2950 1 s 2974 3580 0 )
+insert ( 10804 4081 2950 2950 2 s 2976 3580 0 )
+insert ( 10805 4081 2950 2950 3 s 2972 3580 0 )
+insert ( 10806 4081 2950 2950 4 s 2977 3580 0 )
+insert ( 10807 4081 2950 2950 5 s 2975 3580 0 )
+insert ( 10808 4103 3831 3831 1 s 3893 3580 0 )
+insert ( 10809 4103 3831 3831 2 s 3895 3580 0 )
+insert ( 10810 4103 3831 3831 3 s 3888 3580 0 )
+insert ( 10811 4103 3831 3831 4 s 3896 3580 0 )
+insert ( 10812 4103 3831 3831 5 s 3894 3580 0 )
+insert ( 10813 4103 3831 3831 7 s 3890 3580 0 )
+insert ( 10814 4103 3831 3831 8 s 3892 3580 0 )
+insert ( 10815 4103 3831 2283 16 s 3889 3580 0 )
+insert ( 10816 4103 3831 3831 17 s 3897 3580 0 )
+insert ( 10817 4103 3831 3831 18 s 3882 3580 0 )
+insert ( 10818 4103 3831 3831 20 s 3884 3580 0 )
+insert ( 10819 4103 3831 3831 21 s 3885 3580 0 )
+insert ( 10820 4103 3831 3831 22 s 3887 3580 0 )
+insert ( 10821 4103 3831 3831 23 s 3886 3580 0 )
+insert ( 10822 4082 3220 3220 1 s 3224 3580 0 )
+insert ( 10823 4082 3220 3220 2 s 3226 3580 0 )
+insert ( 10824 4082 3220 3220 3 s 3222 3580 0 )
+insert ( 10825 4082 3220 3220 4 s 3227 3580 0 )
+insert ( 10826 4082 3220 3220 5 s 3225 3580 0 )
+insert ( 10827 4104 603 603 1 s 493 3580 0 )
+insert ( 10828 4104 603 603 2 s 494 3580 0 )
+insert ( 10829 4104 603 603 3 s 500 3580 0 )
+insert ( 10830 4104 603 603 4 s 495 3580 0 )
+insert ( 10831 4104 603 603 5 s 496 3580 0 )
+insert ( 10832 4104 603 603 6 s 499 3580 0 )
+insert ( 10833 4104 603 603 7 s 498 3580 0 )
+insert ( 10834 4104 603 603 8 s 497 3580 0 )
+insert ( 10835 4104 603 603 9 s 2571 3580 0 )
+insert ( 10836 4104 603 603 10 s 2570 3580 0 )
+insert ( 10837 4104 603 603 11 s 2573 3580 0 )
+insert ( 10838 4104 603 603 12 s 2572 3580 0 )
+insert ( 10839 4104 603 600 7 s 433 3580 0 )
+close pg_amop
+create pg_amproc 2603
+ (
+ oid = oid ,
+ amprocfamily = oid ,
+ amproclefttype = oid ,
+ amprocrighttype = oid ,
+ amprocnum = int2 ,
+ amproc = regproc
+ )
+open pg_amproc
+insert ( 10840 397 2277 2277 1 382 )
+insert ( 10841 423 1560 1560 1 1596 )
+insert ( 10842 423 1560 1560 4 5051 )
+insert ( 10843 424 16 16 1 1693 )
+insert ( 10844 424 16 16 4 5051 )
+insert ( 10845 426 1042 1042 1 1078 )
+insert ( 10846 426 1042 1042 2 3328 )
+insert ( 10847 426 1042 1042 4 5050 )
+insert ( 10848 428 17 17 1 1954 )
+insert ( 10849 428 17 17 2 3331 )
+insert ( 10850 428 17 17 4 5051 )
+insert ( 10851 429 18 18 1 358 )
+insert ( 10852 429 18 18 4 5051 )
+insert ( 10853 434 1082 1082 1 1092 )
+insert ( 10854 434 1082 1082 2 3136 )
+insert ( 10855 434 1082 1082 4 5051 )
+insert ( 10856 434 1082 1114 1 2344 )
+insert ( 10857 434 1082 1184 1 2357 )
+insert ( 10858 434 1114 1114 1 2045 )
+insert ( 10859 434 1114 1114 2 3137 )
+insert ( 10860 434 1114 1114 4 5051 )
+insert ( 10861 434 1114 1082 1 2370 )
+insert ( 10862 434 1114 1184 1 2526 )
+insert ( 10863 434 1184 1184 1 1314 )
+insert ( 10864 434 1184 1184 2 3137 )
+insert ( 10865 434 1184 1184 4 5051 )
+insert ( 10866 434 1184 1082 1 2383 )
+insert ( 10867 434 1184 1114 1 2533 )
+insert ( 10868 434 1082 1186 3 4133 )
+insert ( 10869 434 1114 1186 3 4134 )
+insert ( 10870 434 1184 1186 3 4135 )
+insert ( 10871 1970 700 700 1 354 )
+insert ( 10872 1970 700 700 2 3132 )
+insert ( 10873 1970 700 701 1 2194 )
+insert ( 10874 1970 701 701 1 355 )
+insert ( 10875 1970 701 701 2 3133 )
+insert ( 10876 1970 701 700 1 2195 )
+insert ( 10877 1970 701 701 3 4139 )
+insert ( 10878 1970 700 701 3 4140 )
+insert ( 10879 1974 869 869 1 926 )
+insert ( 10880 1974 869 869 2 5033 )
+insert ( 10881 1974 869 869 4 5051 )
+insert ( 10882 1976 21 21 1 350 )
+insert ( 10883 1976 21 21 2 3129 )
+insert ( 10884 1976 21 21 4 5051 )
+insert ( 10885 1976 21 23 1 2190 )
+insert ( 10886 1976 21 20 1 2192 )
+insert ( 10887 1976 21 20 3 4130 )
+insert ( 10888 1976 21 23 3 4131 )
+insert ( 10889 1976 21 21 3 4132 )
+insert ( 10890 1976 23 23 1 351 )
+insert ( 10891 1976 23 23 2 3130 )
+insert ( 10892 1976 23 23 4 5051 )
+insert ( 10893 1976 23 20 1 2188 )
+insert ( 10894 1976 23 21 1 2191 )
+insert ( 10895 1976 23 20 3 4127 )
+insert ( 10896 1976 23 23 3 4128 )
+insert ( 10897 1976 23 21 3 4129 )
+insert ( 10898 1976 20 20 1 842 )
+insert ( 10899 1976 20 20 2 3131 )
+insert ( 10900 1976 20 20 4 5051 )
+insert ( 10901 1976 20 23 1 2189 )
+insert ( 10902 1976 20 21 1 2193 )
+insert ( 10903 1976 20 20 3 4126 )
+insert ( 10904 1982 1186 1186 1 1315 )
+insert ( 10905 1982 1186 1186 3 4136 )
+insert ( 10906 1982 1186 1186 4 5051 )
+insert ( 10907 1984 829 829 1 836 )
+insert ( 10908 1984 829 829 2 3359 )
+insert ( 10909 1984 829 829 4 5051 )
+insert ( 10910 1988 1700 1700 1 1769 )
+insert ( 10911 1988 1700 1700 2 3283 )
+insert ( 10912 1988 1700 1700 3 4141 )
+insert ( 10913 1989 26 26 1 356 )
+insert ( 10914 1989 26 26 2 3134 )
+insert ( 10915 1989 26 26 4 5051 )
+insert ( 10916 1991 30 30 1 404 )
+insert ( 10917 1991 30 30 4 5051 )
+insert ( 10918 1994 25 25 1 360 )
+insert ( 10919 1994 25 25 2 3255 )
+insert ( 10920 1994 25 25 4 5050 )
+insert ( 10921 1994 19 19 1 359 )
+insert ( 10922 1994 19 19 2 3135 )
+insert ( 10923 1994 19 19 4 5050 )
+insert ( 10924 1994 19 25 1 246 )
+insert ( 10925 1994 25 19 1 253 )
+insert ( 10926 1996 1083 1083 1 1107 )
+insert ( 10927 1996 1083 1083 4 5051 )
+insert ( 10928 1996 1083 1186 3 4137 )
+insert ( 10929 2000 1266 1266 1 1358 )
+insert ( 10930 2000 1266 1266 4 5051 )
+insert ( 10931 2000 1266 1186 3 4138 )
+insert ( 10932 2002 1562 1562 1 1672 )
+insert ( 10933 2002 1562 1562 4 5051 )
+insert ( 10934 2095 25 25 1 2166 )
+insert ( 10935 2095 25 25 2 3332 )
+insert ( 10936 2095 25 25 4 5051 )
+insert ( 10937 2097 1042 1042 1 2180 )
+insert ( 10938 2097 1042 1042 2 3333 )
+insert ( 10939 2097 1042 1042 4 5051 )
+insert ( 10940 2099 790 790 1 377 )
+insert ( 10941 2099 790 790 4 5051 )
+insert ( 10942 2789 27 27 1 2794 )
+insert ( 10943 2789 27 27 4 5051 )
+insert ( 10944 2968 2950 2950 1 2960 )
+insert ( 10945 2968 2950 2950 2 3300 )
+insert ( 10946 2968 2950 2950 4 5051 )
+insert ( 10947 2994 2249 2249 1 2987 )
+insert ( 10948 3194 2249 2249 1 3187 )
+insert ( 10949 3253 3220 3220 1 3251 )
+insert ( 10950 3253 3220 3220 4 5051 )
+insert ( 10951 3371 774 774 1 4119 )
+insert ( 10952 3371 774 774 4 5051 )
+insert ( 10953 3522 3500 3500 1 3514 )
+insert ( 10954 3522 3500 3500 4 5051 )
+insert ( 10955 3626 3614 3614 1 3622 )
+insert ( 10956 3683 3615 3615 1 3668 )
+insert ( 10957 3901 3831 3831 1 3870 )
+insert ( 10958 4033 3802 3802 1 4044 )
+insert ( 10959 5067 5069 5069 1 5096 )
+insert ( 10960 5067 5069 5069 4 5051 )
+insert ( 10961 427 1042 1042 1 1080 )
+insert ( 10962 427 1042 1042 2 972 )
+insert ( 10963 431 18 18 1 454 )
+insert ( 10964 431 18 18 2 446 )
+insert ( 10965 435 1082 1082 1 450 )
+insert ( 10966 435 1082 1082 2 425 )
+insert ( 10967 627 2277 2277 1 626 )
+insert ( 10968 627 2277 2277 2 782 )
+insert ( 10969 1971 700 700 1 451 )
+insert ( 10970 1971 700 700 2 443 )
+insert ( 10971 1971 701 701 1 452 )
+insert ( 10972 1971 701 701 2 444 )
+insert ( 10973 1975 869 869 1 422 )
+insert ( 10974 1975 869 869 2 779 )
+insert ( 10975 1977 21 21 1 449 )
+insert ( 10976 1977 21 21 2 441 )
+insert ( 10977 1977 23 23 1 450 )
+insert ( 10978 1977 23 23 2 425 )
+insert ( 10979 1977 20 20 1 949 )
+insert ( 10980 1977 20 20 2 442 )
+insert ( 10981 1983 1186 1186 1 1697 )
+insert ( 10982 1983 1186 1186 2 3418 )
+insert ( 10983 1985 829 829 1 399 )
+insert ( 10984 1985 829 829 2 778 )
+insert ( 10985 1990 26 26 1 453 )
+insert ( 10986 1990 26 26 2 445 )
+insert ( 10987 1992 30 30 1 457 )
+insert ( 10988 1992 30 30 2 776 )
+insert ( 10989 1995 25 25 1 400 )
+insert ( 10990 1995 25 25 2 448 )
+insert ( 10991 1995 19 19 1 455 )
+insert ( 10992 1995 19 19 2 447 )
+insert ( 10993 1997 1083 1083 1 1688 )
+insert ( 10994 1997 1083 1083 2 3409 )
+insert ( 10995 1998 1700 1700 1 432 )
+insert ( 10996 1998 1700 1700 2 780 )
+insert ( 10997 1999 1184 1184 1 2039 )
+insert ( 10998 1999 1184 1184 2 3411 )
+insert ( 10999 2001 1266 1266 1 1696 )
+insert ( 11000 2001 1266 1266 2 3410 )
+insert ( 11001 2040 1114 1114 1 2039 )
+insert ( 11002 2040 1114 1114 2 3411 )
+insert ( 11003 2222 16 16 1 454 )
+insert ( 11004 2222 16 16 2 446 )
+insert ( 11005 2223 17 17 1 456 )
+insert ( 11006 2223 17 17 2 772 )
+insert ( 11007 2225 28 28 1 450 )
+insert ( 11008 2225 28 28 2 425 )
+insert ( 11009 5032 5069 5069 1 949 )
+insert ( 11010 5032 5069 5069 2 442 )
+insert ( 11011 2226 29 29 1 450 )
+insert ( 11012 2226 29 29 2 425 )
+insert ( 11013 2227 27 27 1 2233 )
+insert ( 11014 2227 27 27 2 2234 )
+insert ( 11015 2229 25 25 1 400 )
+insert ( 11016 2229 25 25 2 448 )
+insert ( 11017 2231 1042 1042 1 1080 )
+insert ( 11018 2231 1042 1042 2 972 )
+insert ( 11019 2235 1033 1033 1 329 )
+insert ( 11020 2235 1033 1033 2 777 )
+insert ( 11021 2969 2950 2950 1 2963 )
+insert ( 11022 2969 2950 2950 2 3412 )
+insert ( 11023 3254 3220 3220 1 3252 )
+insert ( 11024 3254 3220 3220 2 3413 )
+insert ( 11025 3372 774 774 1 328 )
+insert ( 11026 3372 774 774 2 781 )
+insert ( 11027 3523 3500 3500 1 3515 )
+insert ( 11028 3523 3500 3500 2 3414 )
+insert ( 11029 3903 3831 3831 1 3902 )
+insert ( 11030 3903 3831 3831 2 3417 )
+insert ( 11031 4034 3802 3802 1 4045 )
+insert ( 11032 4034 3802 3802 2 3416 )
+insert ( 11033 1029 600 600 1 2179 )
+insert ( 11034 1029 600 600 2 2583 )
+insert ( 11035 1029 600 600 3 1030 )
+insert ( 11036 1029 600 600 5 2581 )
+insert ( 11037 1029 600 600 6 2582 )
+insert ( 11038 1029 600 600 7 2584 )
+insert ( 11039 1029 600 600 8 3064 )
+insert ( 11040 1029 600 600 9 3282 )
+insert ( 11041 2593 603 603 1 2578 )
+insert ( 11042 2593 603 603 2 2583 )
+insert ( 11043 2593 603 603 5 2581 )
+insert ( 11044 2593 603 603 6 2582 )
+insert ( 11045 2593 603 603 7 2584 )
+insert ( 11046 2593 603 603 8 3998 )
+insert ( 11047 2594 604 604 1 2585 )
+insert ( 11048 2594 604 604 2 2583 )
+insert ( 11049 2594 604 604 3 2586 )
+insert ( 11050 2594 604 604 5 2581 )
+insert ( 11051 2594 604 604 6 2582 )
+insert ( 11052 2594 604 604 7 2584 )
+insert ( 11053 2594 604 604 8 3288 )
+insert ( 11054 2595 718 718 1 2591 )
+insert ( 11055 2595 718 718 2 2583 )
+insert ( 11056 2595 718 718 3 2592 )
+insert ( 11057 2595 718 718 5 2581 )
+insert ( 11058 2595 718 718 6 2582 )
+insert ( 11059 2595 718 718 7 2584 )
+insert ( 11060 2595 718 718 8 3280 )
+insert ( 11061 3655 3614 3614 1 3654 )
+insert ( 11062 3655 3614 3614 2 3651 )
+insert ( 11063 3655 3614 3614 3 3648 )
+insert ( 11064 3655 3614 3614 4 3649 )
+insert ( 11065 3655 3614 3614 5 3653 )
+insert ( 11066 3655 3614 3614 6 3650 )
+insert ( 11067 3655 3614 3614 7 3652 )
+insert ( 11068 3655 3614 3614 10 3434 )
+insert ( 11069 3702 3615 3615 1 3701 )
+insert ( 11070 3702 3615 3615 2 3698 )
+insert ( 11071 3702 3615 3615 3 3695 )
+insert ( 11072 3702 3615 3615 5 3700 )
+insert ( 11073 3702 3615 3615 6 3697 )
+insert ( 11074 3702 3615 3615 7 3699 )
+insert ( 11075 3919 3831 3831 1 3875 )
+insert ( 11076 3919 3831 3831 2 3876 )
+insert ( 11077 3919 3831 3831 5 3879 )
+insert ( 11078 3919 3831 3831 6 3880 )
+insert ( 11079 3919 3831 3831 7 3881 )
+insert ( 11080 3550 869 869 1 3553 )
+insert ( 11081 3550 869 869 2 3554 )
+insert ( 11082 3550 869 869 3 3555 )
+insert ( 11083 3550 869 869 5 3557 )
+insert ( 11084 3550 869 869 6 3558 )
+insert ( 11085 3550 869 869 7 3559 )
+insert ( 11086 3550 869 869 9 3573 )
+insert ( 11087 2745 2277 2277 2 2743 )
+insert ( 11088 2745 2277 2277 3 2774 )
+insert ( 11089 2745 2277 2277 4 2744 )
+insert ( 11090 2745 2277 2277 6 3920 )
+insert ( 11091 3659 3614 3614 1 3724 )
+insert ( 11092 3659 3614 3614 2 3656 )
+insert ( 11093 3659 3614 3614 3 3657 )
+insert ( 11094 3659 3614 3614 4 3658 )
+insert ( 11095 3659 3614 3614 5 2700 )
+insert ( 11096 3659 3614 3614 6 3921 )
+insert ( 11097 4036 3802 3802 1 3480 )
+insert ( 11098 4036 3802 3802 2 3482 )
+insert ( 11099 4036 3802 3802 3 3483 )
+insert ( 11100 4036 3802 3802 4 3484 )
+insert ( 11101 4036 3802 3802 6 3488 )
+insert ( 11102 4037 3802 3802 1 351 )
+insert ( 11103 4037 3802 3802 2 3485 )
+insert ( 11104 4037 3802 3802 3 3486 )
+insert ( 11105 4037 3802 3802 4 3487 )
+insert ( 11106 4037 3802 3802 6 3489 )
+insert ( 11107 3474 3831 3831 1 3469 )
+insert ( 11108 3474 3831 3831 2 3470 )
+insert ( 11109 3474 3831 3831 3 3471 )
+insert ( 11110 3474 3831 3831 4 3472 )
+insert ( 11111 3474 3831 3831 5 3473 )
+insert ( 11112 3794 869 869 1 3795 )
+insert ( 11113 3794 869 869 2 3796 )
+insert ( 11114 3794 869 869 3 3797 )
+insert ( 11115 3794 869 869 4 3798 )
+insert ( 11116 3794 869 869 5 3799 )
+insert ( 11117 4015 600 600 1 4018 )
+insert ( 11118 4015 600 600 2 4019 )
+insert ( 11119 4015 600 600 3 4020 )
+insert ( 11120 4015 600 600 4 4021 )
+insert ( 11121 4015 600 600 5 4022 )
+insert ( 11122 4016 600 600 1 4023 )
+insert ( 11123 4016 600 600 2 4024 )
+insert ( 11124 4016 600 600 3 4025 )
+insert ( 11125 4016 600 600 4 4026 )
+insert ( 11126 4016 600 600 5 4022 )
+insert ( 11127 4017 25 25 1 4027 )
+insert ( 11128 4017 25 25 2 4028 )
+insert ( 11129 4017 25 25 3 4029 )
+insert ( 11130 4017 25 25 4 4030 )
+insert ( 11131 4017 25 25 5 4031 )
+insert ( 11132 5000 603 603 1 5012 )
+insert ( 11133 5000 603 603 2 5013 )
+insert ( 11134 5000 603 603 3 5014 )
+insert ( 11135 5000 603 603 4 5015 )
+insert ( 11136 5000 603 603 5 5016 )
+insert ( 11137 5008 604 604 1 5010 )
+insert ( 11138 5008 604 604 2 5013 )
+insert ( 11139 5008 604 604 3 5014 )
+insert ( 11140 5008 604 604 4 5015 )
+insert ( 11141 5008 604 604 5 5016 )
+insert ( 11142 5008 604 604 6 5011 )
+insert ( 11143 4064 17 17 1 3383 )
+insert ( 11144 4064 17 17 2 3384 )
+insert ( 11145 4064 17 17 3 3385 )
+insert ( 11146 4064 17 17 4 3386 )
+insert ( 11147 4062 18 18 1 3383 )
+insert ( 11148 4062 18 18 2 3384 )
+insert ( 11149 4062 18 18 3 3385 )
+insert ( 11150 4062 18 18 4 3386 )
+insert ( 11151 4065 19 19 1 3383 )
+insert ( 11152 4065 19 19 2 3384 )
+insert ( 11153 4065 19 19 3 3385 )
+insert ( 11154 4065 19 19 4 3386 )
+insert ( 11155 4054 20 20 1 3383 )
+insert ( 11156 4054 20 20 2 3384 )
+insert ( 11157 4054 20 20 3 3385 )
+insert ( 11158 4054 20 20 4 3386 )
+insert ( 11159 4054 20 21 1 3383 )
+insert ( 11160 4054 20 21 2 3384 )
+insert ( 11161 4054 20 21 3 3385 )
+insert ( 11162 4054 20 21 4 3386 )
+insert ( 11163 4054 20 23 1 3383 )
+insert ( 11164 4054 20 23 2 3384 )
+insert ( 11165 4054 20 23 3 3385 )
+insert ( 11166 4054 20 23 4 3386 )
+insert ( 11167 4054 21 21 1 3383 )
+insert ( 11168 4054 21 21 2 3384 )
+insert ( 11169 4054 21 21 3 3385 )
+insert ( 11170 4054 21 21 4 3386 )
+insert ( 11171 4054 21 20 1 3383 )
+insert ( 11172 4054 21 20 2 3384 )
+insert ( 11173 4054 21 20 3 3385 )
+insert ( 11174 4054 21 20 4 3386 )
+insert ( 11175 4054 21 23 1 3383 )
+insert ( 11176 4054 21 23 2 3384 )
+insert ( 11177 4054 21 23 3 3385 )
+insert ( 11178 4054 21 23 4 3386 )
+insert ( 11179 4054 23 23 1 3383 )
+insert ( 11180 4054 23 23 2 3384 )
+insert ( 11181 4054 23 23 3 3385 )
+insert ( 11182 4054 23 23 4 3386 )
+insert ( 11183 4054 23 20 1 3383 )
+insert ( 11184 4054 23 20 2 3384 )
+insert ( 11185 4054 23 20 3 3385 )
+insert ( 11186 4054 23 20 4 3386 )
+insert ( 11187 4054 23 21 1 3383 )
+insert ( 11188 4054 23 21 2 3384 )
+insert ( 11189 4054 23 21 3 3385 )
+insert ( 11190 4054 23 21 4 3386 )
+insert ( 11191 4056 25 25 1 3383 )
+insert ( 11192 4056 25 25 2 3384 )
+insert ( 11193 4056 25 25 3 3385 )
+insert ( 11194 4056 25 25 4 3386 )
+insert ( 11195 4068 26 26 1 3383 )
+insert ( 11196 4068 26 26 2 3384 )
+insert ( 11197 4068 26 26 3 3385 )
+insert ( 11198 4068 26 26 4 3386 )
+insert ( 11199 4069 27 27 1 3383 )
+insert ( 11200 4069 27 27 2 3384 )
+insert ( 11201 4069 27 27 3 3385 )
+insert ( 11202 4069 27 27 4 3386 )
+insert ( 11203 4070 700 700 1 3383 )
+insert ( 11204 4070 700 700 2 3384 )
+insert ( 11205 4070 700 700 3 3385 )
+insert ( 11206 4070 700 700 4 3386 )
+insert ( 11207 4070 700 701 1 3383 )
+insert ( 11208 4070 700 701 2 3384 )
+insert ( 11209 4070 700 701 3 3385 )
+insert ( 11210 4070 700 701 4 3386 )
+insert ( 11211 4070 701 701 1 3383 )
+insert ( 11212 4070 701 701 2 3384 )
+insert ( 11213 4070 701 701 3 3385 )
+insert ( 11214 4070 701 701 4 3386 )
+insert ( 11215 4070 701 700 1 3383 )
+insert ( 11216 4070 701 700 2 3384 )
+insert ( 11217 4070 701 700 3 3385 )
+insert ( 11218 4070 701 700 4 3386 )
+insert ( 11219 4074 829 829 1 3383 )
+insert ( 11220 4074 829 829 2 3384 )
+insert ( 11221 4074 829 829 3 3385 )
+insert ( 11222 4074 829 829 4 3386 )
+insert ( 11223 4109 774 774 1 3383 )
+insert ( 11224 4109 774 774 2 3384 )
+insert ( 11225 4109 774 774 3 3385 )
+insert ( 11226 4109 774 774 4 3386 )
+insert ( 11227 4075 869 869 1 3383 )
+insert ( 11228 4075 869 869 2 3384 )
+insert ( 11229 4075 869 869 3 3385 )
+insert ( 11230 4075 869 869 4 3386 )
+insert ( 11231 4102 869 869 1 4105 )
+insert ( 11232 4102 869 869 2 4106 )
+insert ( 11233 4102 869 869 3 4107 )
+insert ( 11234 4102 869 869 4 4108 )
+insert ( 11235 4102 869 869 11 4063 )
+insert ( 11236 4102 869 869 12 4071 )
+insert ( 11237 4102 869 869 13 930 )
+insert ( 11238 4076 1042 1042 1 3383 )
+insert ( 11239 4076 1042 1042 2 3384 )
+insert ( 11240 4076 1042 1042 3 3385 )
+insert ( 11241 4076 1042 1042 4 3386 )
+insert ( 11242 4077 1083 1083 1 3383 )
+insert ( 11243 4077 1083 1083 2 3384 )
+insert ( 11244 4077 1083 1083 3 3385 )
+insert ( 11245 4077 1083 1083 4 3386 )
+insert ( 11246 4059 1114 1114 1 3383 )
+insert ( 11247 4059 1114 1114 2 3384 )
+insert ( 11248 4059 1114 1114 3 3385 )
+insert ( 11249 4059 1114 1114 4 3386 )
+insert ( 11250 4059 1114 1184 1 3383 )
+insert ( 11251 4059 1114 1184 2 3384 )
+insert ( 11252 4059 1114 1184 3 3385 )
+insert ( 11253 4059 1114 1184 4 3386 )
+insert ( 11254 4059 1114 1082 1 3383 )
+insert ( 11255 4059 1114 1082 2 3384 )
+insert ( 11256 4059 1114 1082 3 3385 )
+insert ( 11257 4059 1114 1082 4 3386 )
+insert ( 11258 4059 1184 1184 1 3383 )
+insert ( 11259 4059 1184 1184 2 3384 )
+insert ( 11260 4059 1184 1184 3 3385 )
+insert ( 11261 4059 1184 1184 4 3386 )
+insert ( 11262 4059 1184 1114 1 3383 )
+insert ( 11263 4059 1184 1114 2 3384 )
+insert ( 11264 4059 1184 1114 3 3385 )
+insert ( 11265 4059 1184 1114 4 3386 )
+insert ( 11266 4059 1184 1082 1 3383 )
+insert ( 11267 4059 1184 1082 2 3384 )
+insert ( 11268 4059 1184 1082 3 3385 )
+insert ( 11269 4059 1184 1082 4 3386 )
+insert ( 11270 4059 1082 1082 1 3383 )
+insert ( 11271 4059 1082 1082 2 3384 )
+insert ( 11272 4059 1082 1082 3 3385 )
+insert ( 11273 4059 1082 1082 4 3386 )
+insert ( 11274 4059 1082 1114 1 3383 )
+insert ( 11275 4059 1082 1114 2 3384 )
+insert ( 11276 4059 1082 1114 3 3385 )
+insert ( 11277 4059 1082 1114 4 3386 )
+insert ( 11278 4059 1082 1184 1 3383 )
+insert ( 11279 4059 1082 1184 2 3384 )
+insert ( 11280 4059 1082 1184 3 3385 )
+insert ( 11281 4059 1082 1184 4 3386 )
+insert ( 11282 4078 1186 1186 1 3383 )
+insert ( 11283 4078 1186 1186 2 3384 )
+insert ( 11284 4078 1186 1186 3 3385 )
+insert ( 11285 4078 1186 1186 4 3386 )
+insert ( 11286 4058 1266 1266 1 3383 )
+insert ( 11287 4058 1266 1266 2 3384 )
+insert ( 11288 4058 1266 1266 3 3385 )
+insert ( 11289 4058 1266 1266 4 3386 )
+insert ( 11290 4079 1560 1560 1 3383 )
+insert ( 11291 4079 1560 1560 2 3384 )
+insert ( 11292 4079 1560 1560 3 3385 )
+insert ( 11293 4079 1560 1560 4 3386 )
+insert ( 11294 4080 1562 1562 1 3383 )
+insert ( 11295 4080 1562 1562 2 3384 )
+insert ( 11296 4080 1562 1562 3 3385 )
+insert ( 11297 4080 1562 1562 4 3386 )
+insert ( 11298 4055 1700 1700 1 3383 )
+insert ( 11299 4055 1700 1700 2 3384 )
+insert ( 11300 4055 1700 1700 3 3385 )
+insert ( 11301 4055 1700 1700 4 3386 )
+insert ( 11302 4081 2950 2950 1 3383 )
+insert ( 11303 4081 2950 2950 2 3384 )
+insert ( 11304 4081 2950 2950 3 3385 )
+insert ( 11305 4081 2950 2950 4 3386 )
+insert ( 11306 4103 3831 3831 1 4105 )
+insert ( 11307 4103 3831 3831 2 4106 )
+insert ( 11308 4103 3831 3831 3 4107 )
+insert ( 11309 4103 3831 3831 4 4108 )
+insert ( 11310 4103 3831 3831 11 4057 )
+insert ( 11311 4103 3831 3831 13 3859 )
+insert ( 11312 4103 3831 3831 14 3850 )
+insert ( 11313 4082 3220 3220 1 3383 )
+insert ( 11314 4082 3220 3220 2 3384 )
+insert ( 11315 4082 3220 3220 3 3385 )
+insert ( 11316 4082 3220 3220 4 3386 )
+insert ( 11317 4104 603 603 1 4105 )
+insert ( 11318 4104 603 603 2 4106 )
+insert ( 11319 4104 603 603 3 4107 )
+insert ( 11320 4104 603 603 4 4108 )
+insert ( 11321 4104 603 603 11 4067 )
+insert ( 11322 4104 603 603 13 187 )
+close pg_amproc
+create pg_language 2612
+ (
+ oid = oid ,
+ lanname = name ,
+ lanowner = oid ,
+ lanispl = bool ,
+ lanpltrusted = bool ,
+ lanplcallfoid = oid ,
+ laninline = oid ,
+ lanvalidator = oid ,
+ lanacl = _aclitem
+ )
+open pg_language
+insert ( 12 internal 10 f f 0 0 2246 _null_ )
+insert ( 13 c 10 f f 0 0 2247 _null_ )
+insert ( 14 sql 10 f t 0 0 2248 _null_ )
+close pg_language
+create pg_largeobject_metadata 2995
+ (
+ oid = oid ,
+ lomowner = oid ,
+ lomacl = _aclitem
+ )
+open pg_largeobject_metadata
+close pg_largeobject_metadata
+create pg_largeobject 2613
+ (
+ loid = oid ,
+ pageno = int4 ,
+ data = bytea FORCE NOT NULL
+ )
+open pg_largeobject
+close pg_largeobject
+create pg_aggregate 2600
+ (
+ aggfnoid = regproc ,
+ aggkind = char ,
+ aggnumdirectargs = int2 ,
+ aggtransfn = regproc ,
+ aggfinalfn = regproc ,
+ aggcombinefn = regproc ,
+ aggserialfn = regproc ,
+ aggdeserialfn = regproc ,
+ aggmtransfn = regproc ,
+ aggminvtransfn = regproc ,
+ aggmfinalfn = regproc ,
+ aggfinalextra = bool ,
+ aggmfinalextra = bool ,
+ aggfinalmodify = char ,
+ aggmfinalmodify = char ,
+ aggsortop = oid ,
+ aggtranstype = oid ,
+ aggtransspace = int4 ,
+ aggmtranstype = oid ,
+ aggmtransspace = int4 ,
+ agginitval = text ,
+ aggminitval = text
+ )
+open pg_aggregate
+insert ( 2100 n 0 2746 3389 2785 2786 2787 2746 3387 3389 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2101 n 0 1963 1964 3324 - - 1963 3571 1964 f f r r 0 1016 0 1016 0 "{0,0}" "{0,0}" )
+insert ( 2102 n 0 1962 1964 3324 - - 1962 3570 1964 f f r r 0 1016 0 1016 0 "{0,0}" "{0,0}" )
+insert ( 2103 n 0 2858 1837 3337 2740 2741 2858 3548 1837 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2104 n 0 208 1830 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2105 n 0 222 1830 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2106 n 0 1843 1844 3325 - - 1843 3549 1844 f f r r 0 1187 0 1187 0 "{0 second,0 second}" "{0 second,0 second}" )
+insert ( 2107 n 0 2746 3388 2785 2786 2787 2746 3387 3388 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2108 n 0 1841 - 463 - - 1963 3571 3572 f f r r 0 20 0 1016 0 _null_ "{0,0}" )
+insert ( 2109 n 0 1840 - 463 - - 1962 3570 3572 f f r r 0 20 0 1016 0 _null_ "{0,0}" )
+insert ( 2110 n 0 204 - 204 - - - - - f f r r 0 700 0 0 0 _null_ _null_ )
+insert ( 2111 n 0 218 - 218 - - - - - f f r r 0 701 0 0 0 _null_ _null_ )
+insert ( 2112 n 0 894 - 894 - - 894 895 - f f r r 0 790 0 790 0 _null_ _null_ )
+insert ( 2113 n 0 1169 - 1169 - - 1169 1170 - f f r r 0 1186 0 1186 0 _null_ _null_ )
+insert ( 2114 n 0 2858 3178 3337 2740 2741 2858 3548 3178 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2115 n 0 1236 - 1236 - - - - - f f r r 413 20 0 0 0 _null_ _null_ )
+insert ( 2116 n 0 768 - 768 - - - - - f f r r 521 23 0 0 0 _null_ _null_ )
+insert ( 2117 n 0 770 - 770 - - - - - f f r r 520 21 0 0 0 _null_ _null_ )
+insert ( 2118 n 0 1965 - 1965 - - - - - f f r r 610 26 0 0 0 _null_ _null_ )
+insert ( 2119 n 0 209 - 209 - - - - - f f r r 623 700 0 0 0 _null_ _null_ )
+insert ( 2120 n 0 223 - 223 - - - - - f f r r 674 701 0 0 0 _null_ _null_ )
+insert ( 2122 n 0 1138 - 1138 - - - - - f f r r 1097 1082 0 0 0 _null_ _null_ )
+insert ( 2123 n 0 1377 - 1377 - - - - - f f r r 1112 1083 0 0 0 _null_ _null_ )
+insert ( 2124 n 0 1379 - 1379 - - - - - f f r r 1554 1266 0 0 0 _null_ _null_ )
+insert ( 2125 n 0 898 - 898 - - - - - f f r r 903 790 0 0 0 _null_ _null_ )
+insert ( 2126 n 0 2036 - 2036 - - - - - f f r r 2064 1114 0 0 0 _null_ _null_ )
+insert ( 2127 n 0 1196 - 1196 - - - - - f f r r 1324 1184 0 0 0 _null_ _null_ )
+insert ( 2128 n 0 1198 - 1198 - - - - - f f r r 1334 1186 0 0 0 _null_ _null_ )
+insert ( 2129 n 0 458 - 458 - - - - - f f r r 666 25 0 0 0 _null_ _null_ )
+insert ( 2130 n 0 1767 - 1767 - - - - - f f r r 1756 1700 0 0 0 _null_ _null_ )
+insert ( 2050 n 0 515 - 515 - - - - - f f r r 1073 2277 0 0 0 _null_ _null_ )
+insert ( 2244 n 0 1063 - 1063 - - - - - f f r r 1060 1042 0 0 0 _null_ _null_ )
+insert ( 2797 n 0 2795 - 2795 - - - - - f f r r 2800 27 0 0 0 _null_ _null_ )
+insert ( 3526 n 0 3525 - 3525 - - - - - f f r r 3519 3500 0 0 0 _null_ _null_ )
+insert ( 3564 n 0 3562 - 3562 - - - - - f f r r 1205 869 0 0 0 _null_ _null_ )
+insert ( 4189 n 0 4187 - 4187 - - - - - f f r r 3225 3220 0 0 0 _null_ _null_ )
+insert ( 2131 n 0 1237 - 1237 - - - - - f f r r 412 20 0 0 0 _null_ _null_ )
+insert ( 2132 n 0 769 - 769 - - - - - f f r r 97 23 0 0 0 _null_ _null_ )
+insert ( 2133 n 0 771 - 771 - - - - - f f r r 95 21 0 0 0 _null_ _null_ )
+insert ( 2134 n 0 1966 - 1966 - - - - - f f r r 609 26 0 0 0 _null_ _null_ )
+insert ( 2135 n 0 211 - 211 - - - - - f f r r 622 700 0 0 0 _null_ _null_ )
+insert ( 2136 n 0 224 - 224 - - - - - f f r r 672 701 0 0 0 _null_ _null_ )
+insert ( 2138 n 0 1139 - 1139 - - - - - f f r r 1095 1082 0 0 0 _null_ _null_ )
+insert ( 2139 n 0 1378 - 1378 - - - - - f f r r 1110 1083 0 0 0 _null_ _null_ )
+insert ( 2140 n 0 1380 - 1380 - - - - - f f r r 1552 1266 0 0 0 _null_ _null_ )
+insert ( 2141 n 0 899 - 899 - - - - - f f r r 902 790 0 0 0 _null_ _null_ )
+insert ( 2142 n 0 2035 - 2035 - - - - - f f r r 2062 1114 0 0 0 _null_ _null_ )
+insert ( 2143 n 0 1195 - 1195 - - - - - f f r r 1322 1184 0 0 0 _null_ _null_ )
+insert ( 2144 n 0 1197 - 1197 - - - - - f f r r 1332 1186 0 0 0 _null_ _null_ )
+insert ( 2145 n 0 459 - 459 - - - - - f f r r 664 25 0 0 0 _null_ _null_ )
+insert ( 2146 n 0 1766 - 1766 - - - - - f f r r 1754 1700 0 0 0 _null_ _null_ )
+insert ( 2051 n 0 516 - 516 - - - - - f f r r 1072 2277 0 0 0 _null_ _null_ )
+insert ( 2245 n 0 1064 - 1064 - - - - - f f r r 1058 1042 0 0 0 _null_ _null_ )
+insert ( 2798 n 0 2796 - 2796 - - - - - f f r r 2799 27 0 0 0 _null_ _null_ )
+insert ( 3527 n 0 3524 - 3524 - - - - - f f r r 3518 3500 0 0 0 _null_ _null_ )
+insert ( 3565 n 0 3563 - 3563 - - - - - f f r r 1203 869 0 0 0 _null_ _null_ )
+insert ( 4190 n 0 4188 - 4188 - - - - - f f r r 3224 3220 0 0 0 _null_ _null_ )
+insert ( 2147 n 0 2804 - 463 - - 2804 3547 - f f r r 0 20 0 20 0 0 0 )
+insert ( 2803 n 0 1219 - 463 - - 1219 3546 - f f r r 0 20 0 20 0 0 0 )
+insert ( 2718 n 0 1836 2514 3341 3335 3336 1836 3569 2514 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2719 n 0 1835 3390 3338 3339 3340 1835 3568 3390 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2720 n 0 1834 3390 3338 3339 3340 1834 3567 3390 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2721 n 0 208 2512 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2722 n 0 222 2512 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2723 n 0 1833 2514 3341 3335 3336 1833 3548 2514 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2641 n 0 1836 1838 3341 3335 3336 1836 3569 1838 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2642 n 0 1835 3391 3338 3339 3340 1835 3568 3391 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2643 n 0 1834 3391 3338 3339 3340 1834 3567 3391 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2644 n 0 208 1831 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2645 n 0 222 1831 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2646 n 0 1833 1838 3341 3335 3336 1833 3548 1838 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2148 n 0 1836 1838 3341 3335 3336 1836 3569 1838 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2149 n 0 1835 3391 3338 3339 3340 1835 3568 3391 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2150 n 0 1834 3391 3338 3339 3340 1834 3567 3391 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2151 n 0 208 1831 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2152 n 0 222 1831 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2153 n 0 1833 1838 3341 3335 3336 1833 3548 1838 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2724 n 0 1836 2596 3341 3335 3336 1836 3569 2596 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2725 n 0 1835 3392 3338 3339 3340 1835 3568 3392 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2726 n 0 1834 3392 3338 3339 3340 1834 3567 3392 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2727 n 0 208 2513 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2728 n 0 222 2513 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2729 n 0 1833 2596 3341 3335 3336 1833 3548 2596 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2712 n 0 1836 1839 3341 3335 3336 1836 3569 1839 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2713 n 0 1835 3393 3338 3339 3340 1835 3568 3393 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2714 n 0 1834 3393 3338 3339 3340 1834 3567 3393 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2715 n 0 208 1832 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2716 n 0 222 1832 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2717 n 0 1833 1839 3341 3335 3336 1833 3548 1839 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2154 n 0 1836 1839 3341 3335 3336 1836 3569 1839 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2155 n 0 1835 3393 3338 3339 3340 1835 3568 3393 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2156 n 0 1834 3393 3338 3339 3340 1834 3567 3393 f f r r 0 2281 48 2281 48 _null_ _null_ )
+insert ( 2157 n 0 208 1832 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2158 n 0 222 1832 276 - - - - - f f r r 0 1022 0 0 0 "{0,0,0}" _null_ )
+insert ( 2159 n 0 1833 1839 3341 3335 3336 1833 3548 1839 f f r r 0 2281 128 2281 128 _null_ _null_ )
+insert ( 2818 n 0 2805 - 463 - - - - - f f r r 0 20 0 0 0 0 _null_ )
+insert ( 2819 n 0 2806 2807 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2820 n 0 2806 2808 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2821 n 0 2806 2809 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2822 n 0 2806 2810 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2823 n 0 2806 2811 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2824 n 0 2806 2812 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2825 n 0 2806 2813 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2826 n 0 2806 2814 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2827 n 0 2806 2815 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2828 n 0 2806 2816 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2829 n 0 2806 2817 3342 - - - - - f f r r 0 1022 0 0 0 "{0,0,0,0,0,0}" _null_ )
+insert ( 2517 n 0 2515 - 2515 - - 3496 3497 3498 f f r r 58 16 0 2281 16 _null_ _null_ )
+insert ( 2518 n 0 2516 - 2516 - - 3496 3497 3499 f f r r 59 16 0 2281 16 _null_ _null_ )
+insert ( 2519 n 0 2515 - 2515 - - 3496 3497 3498 f f r r 58 16 0 2281 16 _null_ _null_ )
+insert ( 2236 n 0 1892 - 1892 - - - - - f f r r 0 21 0 0 0 _null_ _null_ )
+insert ( 2237 n 0 1893 - 1893 - - - - - f f r r 0 21 0 0 0 _null_ _null_ )
+insert ( 2238 n 0 1898 - 1898 - - - - - f f r r 0 23 0 0 0 _null_ _null_ )
+insert ( 2239 n 0 1899 - 1899 - - - - - f f r r 0 23 0 0 0 _null_ _null_ )
+insert ( 2240 n 0 1904 - 1904 - - - - - f f r r 0 20 0 0 0 _null_ _null_ )
+insert ( 2241 n 0 1905 - 1905 - - - - - f f r r 0 20 0 0 0 _null_ _null_ )
+insert ( 2242 n 0 1673 - 1673 - - - - - f f r r 0 1560 0 0 0 _null_ _null_ )
+insert ( 2243 n 0 1674 - 1674 - - - - - f f r r 0 1560 0 0 0 _null_ _null_ )
+insert ( 2901 n 0 2900 - - - - - - - f f r r 0 142 0 0 0 _null_ _null_ )
+insert ( 2335 n 0 2333 2334 - - - - - - t f r r 0 2281 0 0 0 _null_ _null_ )
+insert ( 4053 n 0 4051 4052 - - - - - - t f r r 0 2281 0 0 0 _null_ _null_ )
+insert ( 3538 n 0 3535 3536 - - - - - - f f r r 0 2281 0 0 0 _null_ _null_ )
+insert ( 3545 n 0 3543 3544 - - - - - - f f r r 0 2281 0 0 0 _null_ _null_ )
+insert ( 3175 n 0 3173 3174 - - - - - - f f r r 0 2281 0 0 0 _null_ _null_ )
+insert ( 3197 n 0 3180 3196 - - - - - - f f r r 0 2281 0 0 0 _null_ _null_ )
+insert ( 3267 n 0 3265 3266 - - - - - - f f r r 0 2281 0 0 0 _null_ _null_ )
+insert ( 3270 n 0 3268 3269 - - - - - - f f r r 0 2281 0 0 0 _null_ _null_ )
+insert ( 3972 o 1 3970 3973 - - - - - - t f s s 0 2281 0 0 0 _null_ _null_ )
+insert ( 3974 o 1 3970 3975 - - - - - - f f s s 0 2281 0 0 0 _null_ _null_ )
+insert ( 3976 o 1 3970 3977 - - - - - - f f s s 0 2281 0 0 0 _null_ _null_ )
+insert ( 3978 o 1 3970 3979 - - - - - - t f s s 0 2281 0 0 0 _null_ _null_ )
+insert ( 3980 o 1 3970 3981 - - - - - - f f s s 0 2281 0 0 0 _null_ _null_ )
+insert ( 3982 o 1 3970 3983 - - - - - - f f s s 0 2281 0 0 0 _null_ _null_ )
+insert ( 3984 o 0 3970 3985 - - - - - - t f s s 0 2281 0 0 0 _null_ _null_ )
+insert ( 3986 h 1 3971 3987 - - - - - - t f w w 0 2281 0 0 0 _null_ _null_ )
+insert ( 3988 h 1 3971 3989 - - - - - - t f w w 0 2281 0 0 0 _null_ _null_ )
+insert ( 3990 h 1 3971 3991 - - - - - - t f w w 0 2281 0 0 0 _null_ _null_ )
+insert ( 3992 h 1 3971 3993 - - - - - - t f w w 0 2281 0 0 0 _null_ _null_ )
+close pg_aggregate
+create pg_statistic_ext 3381
+ (
+ oid = oid ,
+ stxrelid = oid ,
+ stxname = name ,
+ stxnamespace = oid ,
+ stxowner = oid ,
+ stxstattarget = int4 ,
+ stxkeys = int2vector ,
+ stxkind = _char FORCE NOT NULL
+ )
+open pg_statistic_ext
+close pg_statistic_ext
+create pg_statistic_ext_data 3429
+ (
+ stxoid = oid ,
+ stxdndistinct = pg_ndistinct ,
+ stxddependencies = pg_dependencies ,
+ stxdmcv = pg_mcv_list
+ )
+open pg_statistic_ext_data
+close pg_statistic_ext_data
+create pg_statistic 2619
+ (
+ starelid = oid ,
+ staattnum = int2 ,
+ stainherit = bool ,
+ stanullfrac = float4 ,
+ stawidth = int4 ,
+ stadistinct = float4 ,
+ stakind1 = int2 ,
+ stakind2 = int2 ,
+ stakind3 = int2 ,
+ stakind4 = int2 ,
+ stakind5 = int2 ,
+ staop1 = oid ,
+ staop2 = oid ,
+ staop3 = oid ,
+ staop4 = oid ,
+ staop5 = oid ,
+ stacoll1 = oid ,
+ stacoll2 = oid ,
+ stacoll3 = oid ,
+ stacoll4 = oid ,
+ stacoll5 = oid ,
+ stanumbers1 = _float4 ,
+ stanumbers2 = _float4 ,
+ stanumbers3 = _float4 ,
+ stanumbers4 = _float4 ,
+ stanumbers5 = _float4 ,
+ stavalues1 = anyarray ,
+ stavalues2 = anyarray ,
+ stavalues3 = anyarray ,
+ stavalues4 = anyarray ,
+ stavalues5 = anyarray
+ )
+open pg_statistic
+close pg_statistic
+create pg_rewrite 2618
+ (
+ oid = oid ,
+ rulename = name ,
+ ev_class = oid ,
+ ev_type = char ,
+ ev_enabled = char ,
+ is_instead = bool ,
+ ev_qual = pg_node_tree FORCE NOT NULL ,
+ ev_action = pg_node_tree FORCE NOT NULL
+ )
+open pg_rewrite
+close pg_rewrite
+create pg_trigger 2620
+ (
+ oid = oid ,
+ tgrelid = oid ,
+ tgparentid = oid ,
+ tgname = name ,
+ tgfoid = oid ,
+ tgtype = int2 ,
+ tgenabled = char ,
+ tgisinternal = bool ,
+ tgconstrrelid = oid ,
+ tgconstrindid = oid ,
+ tgconstraint = oid ,
+ tgdeferrable = bool ,
+ tginitdeferred = bool ,
+ tgnargs = int2 ,
+ tgattr = int2vector ,
+ tgargs = bytea FORCE NOT NULL ,
+ tgqual = pg_node_tree ,
+ tgoldtable = name ,
+ tgnewtable = name
+ )
+open pg_trigger
+close pg_trigger
+create pg_event_trigger 3466
+ (
+ oid = oid ,
+ evtname = name ,
+ evtevent = name ,
+ evtowner = oid ,
+ evtfoid = oid ,
+ evtenabled = char ,
+ evttags = _text
+ )
+open pg_event_trigger
+close pg_event_trigger
+create pg_description 2609
+ (
+ objoid = oid ,
+ classoid = oid ,
+ objsubid = int4 ,
+ description = text FORCE NOT NULL
+ )
+open pg_description
+insert ( 1242 1255 0 "I/O" )
+insert ( 1243 1255 0 "I/O" )
+insert ( 1244 1255 0 "I/O" )
+insert ( 31 1255 0 "I/O" )
+insert ( 1245 1255 0 "I/O" )
+insert ( 33 1255 0 "I/O" )
+insert ( 34 1255 0 "I/O" )
+insert ( 35 1255 0 "I/O" )
+insert ( 38 1255 0 "I/O" )
+insert ( 39 1255 0 "I/O" )
+insert ( 40 1255 0 "I/O" )
+insert ( 41 1255 0 "I/O" )
+insert ( 42 1255 0 "I/O" )
+insert ( 43 1255 0 "I/O" )
+insert ( 44 1255 0 "I/O" )
+insert ( 45 1255 0 "I/O" )
+insert ( 3494 1255 0 "convert proname to regproc" )
+insert ( 3479 1255 0 "convert proname to regprocedure" )
+insert ( 46 1255 0 "I/O" )
+insert ( 47 1255 0 "I/O" )
+insert ( 48 1255 0 "I/O" )
+insert ( 49 1255 0 "I/O" )
+insert ( 50 1255 0 "I/O" )
+insert ( 51 1255 0 "I/O" )
+insert ( 5070 1255 0 "I/O" )
+insert ( 5081 1255 0 "I/O" )
+insert ( 5082 1255 0 "I/O" )
+insert ( 5083 1255 0 "I/O" )
+insert ( 52 1255 0 "I/O" )
+insert ( 53 1255 0 "I/O" )
+insert ( 54 1255 0 "I/O" )
+insert ( 55 1255 0 "I/O" )
+insert ( 5096 1255 0 less-equal-greater )
+insert ( 5071 1255 0 "convert xid8 to xid" )
+insert ( 77 1255 0 "convert char to int4" )
+insert ( 78 1255 0 "convert int4 to char" )
+insert ( 1364 1255 0 "planner support for textregexeq" )
+insert ( 1257 1255 0 length )
+insert ( 89 1255 0 "PostgreSQL version string" )
+insert ( 86 1255 0 "I/O" )
+insert ( 87 1255 0 "I/O" )
+insert ( 88 1255 0 "I/O" )
+insert ( 90 1255 0 "I/O" )
+insert ( 101 1255 0 "restriction selectivity of = and related operators" )
+insert ( 102 1255 0 "restriction selectivity of <> and related operators" )
+insert ( 103 1255 0 "restriction selectivity of < and related operators on scalar datatypes" )
+insert ( 104 1255 0 "restriction selectivity of > and related operators on scalar datatypes" )
+insert ( 105 1255 0 "join selectivity of = and related operators" )
+insert ( 106 1255 0 "join selectivity of <> and related operators" )
+insert ( 107 1255 0 "join selectivity of < and related operators on scalar datatypes" )
+insert ( 108 1255 0 "join selectivity of > and related operators on scalar datatypes" )
+insert ( 336 1255 0 "restriction selectivity of <= and related operators on scalar datatypes" )
+insert ( 337 1255 0 "restriction selectivity of >= and related operators on scalar datatypes" )
+insert ( 386 1255 0 "join selectivity of <= and related operators on scalar datatypes" )
+insert ( 398 1255 0 "join selectivity of >= and related operators on scalar datatypes" )
+insert ( 109 1255 0 "I/O" )
+insert ( 110 1255 0 "I/O" )
+insert ( 111 1255 0 "implementation of deprecated ! and !! factorial operators" )
+insert ( 117 1255 0 "I/O" )
+insert ( 118 1255 0 "I/O" )
+insert ( 119 1255 0 "I/O" )
+insert ( 120 1255 0 "I/O" )
+insert ( 121 1255 0 "I/O" )
+insert ( 122 1255 0 "I/O" )
+insert ( 123 1255 0 "I/O" )
+insert ( 124 1255 0 "I/O" )
+insert ( 139 1255 0 "restriction selectivity for area-comparison operators" )
+insert ( 140 1255 0 "join selectivity for area-comparison operators" )
+insert ( 195 1255 0 "I/O" )
+insert ( 196 1255 0 "I/O" )
+insert ( 197 1255 0 "I/O" )
+insert ( 198 1255 0 "I/O" )
+insert ( 200 1255 0 "I/O" )
+insert ( 201 1255 0 "I/O" )
+insert ( 208 1255 0 "aggregate transition function" )
+insert ( 209 1255 0 "larger of two" )
+insert ( 211 1255 0 "smaller of two" )
+insert ( 214 1255 0 "I/O" )
+insert ( 215 1255 0 "I/O" )
+insert ( 222 1255 0 "aggregate transition function" )
+insert ( 276 1255 0 "aggregate combine function" )
+insert ( 223 1255 0 "larger of two" )
+insert ( 224 1255 0 "smaller of two" )
+insert ( 228 1255 0 "round to nearest integer" )
+insert ( 229 1255 0 "truncate to integer" )
+insert ( 2308 1255 0 "nearest integer >= value" )
+insert ( 2320 1255 0 "nearest integer >= value" )
+insert ( 2309 1255 0 "nearest integer <= value" )
+insert ( 2310 1255 0 "sign of value" )
+insert ( 233 1255 0 "natural exponential (e^x)" )
+insert ( 234 1255 0 "natural logarithm" )
+insert ( 235 1255 0 "convert int2 to float8" )
+insert ( 236 1255 0 "convert int2 to float4" )
+insert ( 237 1255 0 "convert float8 to int2" )
+insert ( 238 1255 0 "convert float4 to int2" )
+insert ( 246 1255 0 less-equal-greater )
+insert ( 253 1255 0 less-equal-greater )
+insert ( 266 1255 0 "concatenate name and oid" )
+insert ( 274 1255 0 "current date and time - increments during transactions" )
+insert ( 320 1255 0 "bucket number of operand in equal-width histogram" )
+insert ( 311 1255 0 "convert float4 to float8" )
+insert ( 312 1255 0 "convert float8 to float4" )
+insert ( 313 1255 0 "convert int2 to int4" )
+insert ( 314 1255 0 "convert int4 to int2" )
+insert ( 316 1255 0 "convert int4 to float8" )
+insert ( 317 1255 0 "convert float8 to int4" )
+insert ( 318 1255 0 "convert int4 to float4" )
+insert ( 319 1255 0 "convert float4 to int4" )
+insert ( 3 1255 0 "row-oriented heap table access method handler" )
+insert ( 330 1255 0 "btree index access method handler" )
+insert ( 331 1255 0 "hash index access method handler" )
+insert ( 332 1255 0 "gist index access method handler" )
+insert ( 333 1255 0 "gin index access method handler" )
+insert ( 334 1255 0 "spgist index access method handler" )
+insert ( 335 1255 0 "brin index access method handler" )
+insert ( 3952 1255 0 "brin: standalone scan new table pages" )
+insert ( 3999 1255 0 "brin: standalone scan new table pages" )
+insert ( 4014 1255 0 "brin: desummarize page range" )
+insert ( 338 1255 0 "validate an operator class" )
+insert ( 636 1255 0 "test property of an index access method" )
+insert ( 637 1255 0 "test property of an index" )
+insert ( 638 1255 0 "test property of an index column" )
+insert ( 676 1255 0 "return name of given index build phase" )
+insert ( 347 1255 0 "I/O" )
+insert ( 348 1255 0 "I/O" )
+insert ( 350 1255 0 less-equal-greater )
+insert ( 3129 1255 0 "sort support" )
+insert ( 351 1255 0 less-equal-greater )
+insert ( 3130 1255 0 "sort support" )
+insert ( 842 1255 0 less-equal-greater )
+insert ( 3131 1255 0 "sort support" )
+insert ( 354 1255 0 less-equal-greater )
+insert ( 3132 1255 0 "sort support" )
+insert ( 355 1255 0 less-equal-greater )
+insert ( 3133 1255 0 "sort support" )
+insert ( 356 1255 0 less-equal-greater )
+insert ( 3134 1255 0 "sort support" )
+insert ( 404 1255 0 less-equal-greater )
+insert ( 358 1255 0 less-equal-greater )
+insert ( 359 1255 0 less-equal-greater )
+insert ( 3135 1255 0 "sort support" )
+insert ( 360 1255 0 less-equal-greater )
+insert ( 3255 1255 0 "sort support" )
+insert ( 5050 1255 0 "equal image" )
+insert ( 377 1255 0 less-equal-greater )
+insert ( 382 1255 0 less-equal-greater )
+insert ( 4126 1255 0 "window RANGE support" )
+insert ( 4127 1255 0 "window RANGE support" )
+insert ( 4128 1255 0 "window RANGE support" )
+insert ( 4129 1255 0 "window RANGE support" )
+insert ( 4130 1255 0 "window RANGE support" )
+insert ( 4131 1255 0 "window RANGE support" )
+insert ( 4132 1255 0 "window RANGE support" )
+insert ( 4139 1255 0 "window RANGE support" )
+insert ( 4140 1255 0 "window RANGE support" )
+insert ( 4141 1255 0 "window RANGE support" )
+insert ( 401 1255 0 "convert char(n) to text" )
+insert ( 406 1255 0 "convert name to text" )
+insert ( 407 1255 0 "convert text to name" )
+insert ( 408 1255 0 "convert name to char(n)" )
+insert ( 409 1255 0 "convert char(n) to name" )
+insert ( 449 1255 0 hash )
+insert ( 441 1255 0 hash )
+insert ( 450 1255 0 hash )
+insert ( 425 1255 0 hash )
+insert ( 949 1255 0 hash )
+insert ( 442 1255 0 hash )
+insert ( 451 1255 0 hash )
+insert ( 443 1255 0 hash )
+insert ( 452 1255 0 hash )
+insert ( 444 1255 0 hash )
+insert ( 453 1255 0 hash )
+insert ( 445 1255 0 hash )
+insert ( 454 1255 0 hash )
+insert ( 446 1255 0 hash )
+insert ( 455 1255 0 hash )
+insert ( 447 1255 0 hash )
+insert ( 400 1255 0 hash )
+insert ( 448 1255 0 hash )
+insert ( 456 1255 0 hash )
+insert ( 772 1255 0 hash )
+insert ( 457 1255 0 hash )
+insert ( 776 1255 0 hash )
+insert ( 329 1255 0 hash )
+insert ( 777 1255 0 hash )
+insert ( 399 1255 0 hash )
+insert ( 778 1255 0 hash )
+insert ( 422 1255 0 hash )
+insert ( 779 1255 0 hash )
+insert ( 432 1255 0 hash )
+insert ( 780 1255 0 hash )
+insert ( 328 1255 0 hash )
+insert ( 781 1255 0 hash )
+insert ( 438 1255 0 "count the number of NULL arguments" )
+insert ( 440 1255 0 "count the number of non-NULL arguments" )
+insert ( 458 1255 0 "larger of two" )
+insert ( 459 1255 0 "smaller of two" )
+insert ( 460 1255 0 "I/O" )
+insert ( 461 1255 0 "I/O" )
+insert ( 480 1255 0 "convert int8 to int4" )
+insert ( 481 1255 0 "convert int4 to int8" )
+insert ( 482 1255 0 "convert int8 to float8" )
+insert ( 483 1255 0 "convert float8 to int8" )
+insert ( 626 1255 0 hash )
+insert ( 782 1255 0 hash )
+insert ( 652 1255 0 "convert int8 to float4" )
+insert ( 653 1255 0 "convert float4 to int8" )
+insert ( 714 1255 0 "convert int8 to int2" )
+insert ( 754 1255 0 "convert int2 to int8" )
+insert ( 668 1255 0 "adjust char() to typmod length" )
+insert ( 3097 1255 0 "planner support for varchar length coercion" )
+insert ( 669 1255 0 "adjust varchar() to typmod length" )
+insert ( 710 1255 0 "deprecated, use current_user instead" )
+insert ( 720 1255 0 "octet length" )
+insert ( 721 1255 0 "get byte" )
+insert ( 722 1255 0 "set byte" )
+insert ( 723 1255 0 "get bit" )
+insert ( 724 1255 0 "set bit" )
+insert ( 749 1255 0 "substitute portion of string" )
+insert ( 752 1255 0 "substitute portion of string" )
+insert ( 745 1255 0 "current user name" )
+insert ( 746 1255 0 "session user name" )
+insert ( 747 1255 0 "array dimensions" )
+insert ( 748 1255 0 "number of array dimensions" )
+insert ( 750 1255 0 "I/O" )
+insert ( 751 1255 0 "I/O" )
+insert ( 2091 1255 0 "array lower dimension" )
+insert ( 2092 1255 0 "array upper dimension" )
+insert ( 2176 1255 0 "array length" )
+insert ( 3179 1255 0 "array cardinality" )
+insert ( 378 1255 0 "append element onto end of array" )
+insert ( 379 1255 0 "prepend element onto front of array" )
+insert ( 394 1255 0 "split delimited text into text[]" )
+insert ( 395 1255 0 "concatenate array elements, using delimiter, into text" )
+insert ( 376 1255 0 "split delimited text into text[], with null string" )
+insert ( 384 1255 0 "concatenate array elements, using delimiter and null string, into text" )
+insert ( 515 1255 0 "larger of two" )
+insert ( 516 1255 0 "smaller of two" )
+insert ( 3277 1255 0 "returns an offset of value in array" )
+insert ( 3278 1255 0 "returns an offset of value in array with start index" )
+insert ( 3279 1255 0 "returns an array of offsets of some value in array" )
+insert ( 1191 1255 0 "array subscripts generator" )
+insert ( 1192 1255 0 "array subscripts generator" )
+insert ( 1193 1255 0 "array constructor with value" )
+insert ( 1286 1255 0 "array constructor with value" )
+insert ( 2331 1255 0 "expand array to set of rows" )
+insert ( 3996 1255 0 "planner support for array_unnest" )
+insert ( 3167 1255 0 "remove any occurrences of an element from an array" )
+insert ( 3168 1255 0 "replace any occurrences of an element in an array" )
+insert ( 2333 1255 0 "aggregate transition function" )
+insert ( 2334 1255 0 "aggregate final function" )
+insert ( 2335 1255 0 "concatenate aggregate input into an array" )
+insert ( 4051 1255 0 "aggregate transition function" )
+insert ( 4052 1255 0 "aggregate final function" )
+insert ( 4053 1255 0 "concatenate aggregate input into an array" )
+insert ( 3218 1255 0 "bucket number of operand given a sorted array of bucket lower bounds" )
+insert ( 3816 1255 0 "array typanalyze" )
+insert ( 3817 1255 0 "restriction selectivity for array-containment operators" )
+insert ( 3818 1255 0 "join selectivity for array-containment operators" )
+insert ( 764 1255 0 "large object import" )
+insert ( 767 1255 0 "large object import" )
+insert ( 765 1255 0 "large object export" )
+insert ( 766 1255 0 increment )
+insert ( 768 1255 0 "larger of two" )
+insert ( 769 1255 0 "smaller of two" )
+insert ( 770 1255 0 "larger of two" )
+insert ( 771 1255 0 "smaller of two" )
+insert ( 849 1255 0 "position of substring" )
+insert ( 1023 1255 0 "planner support for textlike" )
+insert ( 860 1255 0 "convert char to char(n)" )
+insert ( 861 1255 0 "name of the current database" )
+insert ( 817 1255 0 "get the currently executing query" )
+insert ( 886 1255 0 "I/O" )
+insert ( 887 1255 0 "I/O" )
+insert ( 898 1255 0 "larger of two" )
+insert ( 899 1255 0 "smaller of two" )
+insert ( 935 1255 0 "output money amount as words" )
+insert ( 3823 1255 0 "convert money to numeric" )
+insert ( 3824 1255 0 "convert numeric to money" )
+insert ( 3811 1255 0 "convert int4 to money" )
+insert ( 3812 1255 0 "convert int8 to money" )
+insert ( 940 1255 0 modulus )
+insert ( 941 1255 0 modulus )
+insert ( 947 1255 0 modulus )
+insert ( 5044 1255 0 "greatest common divisor" )
+insert ( 5045 1255 0 "greatest common divisor" )
+insert ( 5046 1255 0 "least common multiple" )
+insert ( 5047 1255 0 "least common multiple" )
+insert ( 944 1255 0 "convert text to char" )
+insert ( 946 1255 0 "convert char to text" )
+insert ( 952 1255 0 "large object open" )
+insert ( 953 1255 0 "large object close" )
+insert ( 954 1255 0 "large object read" )
+insert ( 955 1255 0 "large object write" )
+insert ( 956 1255 0 "large object seek" )
+insert ( 3170 1255 0 "large object seek (64 bit)" )
+insert ( 957 1255 0 "large object create" )
+insert ( 715 1255 0 "large object create" )
+insert ( 958 1255 0 "large object position" )
+insert ( 3171 1255 0 "large object position (64 bit)" )
+insert ( 1004 1255 0 "truncate large object" )
+insert ( 3172 1255 0 "truncate large object (64 bit)" )
+insert ( 3457 1255 0 "create new large object with given content" )
+insert ( 3458 1255 0 "read entire large object" )
+insert ( 3459 1255 0 "read large object from offset for length" )
+insert ( 3460 1255 0 "write data at offset" )
+insert ( 964 1255 0 "large object unlink (delete)" )
+insert ( 975 1255 0 "box area" )
+insert ( 976 1255 0 "box width" )
+insert ( 977 1255 0 "box height" )
+insert ( 979 1255 0 "area of a closed path" )
+insert ( 4067 1255 0 "bounding box of two boxes" )
+insert ( 981 1255 0 "box diagonal" )
+insert ( 992 1255 0 "slope between points" )
+insert ( 993 1255 0 "convert points to line segment" )
+insert ( 1026 1255 0 "adjust timestamp to new time zone" )
+insert ( 1031 1255 0 "I/O" )
+insert ( 1032 1255 0 "I/O" )
+insert ( 1035 1255 0 "add/update ACL item" )
+insert ( 1036 1255 0 "remove ACL item" )
+insert ( 1037 1255 0 contains )
+insert ( 1365 1255 0 "make ACL item" )
+insert ( 3943 1255 0 "show hardwired default privileges, primarily for use by the information schema" )
+insert ( 1689 1255 0 "convert ACL item array to table, primarily for use by information schema" )
+insert ( 1044 1255 0 "I/O" )
+insert ( 1045 1255 0 "I/O" )
+insert ( 2913 1255 0 "I/O typmod" )
+insert ( 2914 1255 0 "I/O typmod" )
+insert ( 1046 1255 0 "I/O" )
+insert ( 1047 1255 0 "I/O" )
+insert ( 2915 1255 0 "I/O typmod" )
+insert ( 2916 1255 0 "I/O typmod" )
+insert ( 1063 1255 0 "larger of two" )
+insert ( 1064 1255 0 "smaller of two" )
+insert ( 1078 1255 0 less-equal-greater )
+insert ( 3328 1255 0 "sort support" )
+insert ( 1080 1255 0 hash )
+insert ( 972 1255 0 hash )
+insert ( 1081 1255 0 "format a type oid and atttypmod to canonical SQL" )
+insert ( 1084 1255 0 "I/O" )
+insert ( 1085 1255 0 "I/O" )
+insert ( 1092 1255 0 less-equal-greater )
+insert ( 3136 1255 0 "sort support" )
+insert ( 4133 1255 0 "window RANGE support" )
+insert ( 1107 1255 0 less-equal-greater )
+insert ( 1138 1255 0 "larger of two" )
+insert ( 1139 1255 0 "smaller of two" )
+insert ( 1143 1255 0 "I/O" )
+insert ( 1144 1255 0 "I/O" )
+insert ( 2909 1255 0 "I/O typmod" )
+insert ( 2910 1255 0 "I/O typmod" )
+insert ( 1150 1255 0 "I/O" )
+insert ( 1151 1255 0 "I/O" )
+insert ( 2907 1255 0 "I/O typmod" )
+insert ( 2908 1255 0 "I/O typmod" )
+insert ( 1158 1255 0 "convert UNIX epoch to timestamptz" )
+insert ( 1159 1255 0 "adjust timestamp to new time zone" )
+insert ( 1160 1255 0 "I/O" )
+insert ( 1161 1255 0 "I/O" )
+insert ( 2903 1255 0 "I/O typmod" )
+insert ( 2904 1255 0 "I/O typmod" )
+insert ( 1171 1255 0 "extract field from timestamp with time zone" )
+insert ( 1172 1255 0 "extract field from interval" )
+insert ( 1174 1255 0 "convert date to timestamp with time zone" )
+insert ( 2711 1255 0 "promote groups of 24 hours to numbers of days and promote groups of 30 days to numbers of months" )
+insert ( 1175 1255 0 "promote groups of 24 hours to numbers of days" )
+insert ( 1295 1255 0 "promote groups of 30 days to numbers of months" )
+insert ( 1176 1255 0 "convert date and time to timestamp with time zone" )
+insert ( 1178 1255 0 "convert timestamp with time zone to date" )
+insert ( 1181 1255 0 "age of a transaction ID, in transactions before current transaction" )
+insert ( 3939 1255 0 "age of a multi-transaction ID, in multi-transactions before current multi-transaction" )
+insert ( 1195 1255 0 "smaller of two" )
+insert ( 1196 1255 0 "larger of two" )
+insert ( 1197 1255 0 "smaller of two" )
+insert ( 1198 1255 0 "larger of two" )
+insert ( 1199 1255 0 "date difference preserving months and years" )
+insert ( 3918 1255 0 "planner support for interval length coercion" )
+insert ( 1200 1255 0 "adjust interval precision" )
+insert ( 1215 1255 0 "get description for object id and catalog name" )
+insert ( 1216 1255 0 "get description for table column" )
+insert ( 1993 1255 0 "get description for object id and shared catalog name" )
+insert ( 1217 1255 0 "truncate timestamp with time zone to specified units" )
+insert ( 1284 1255 0 "truncate timestamp with time zone to specified units in specified time zone" )
+insert ( 1218 1255 0 "truncate interval to specified units" )
+insert ( 1219 1255 0 increment )
+insert ( 3546 1255 0 decrement )
+insert ( 2804 1255 0 "increment, ignores second argument" )
+insert ( 3547 1255 0 "decrement, ignores second argument" )
+insert ( 1236 1255 0 "larger of two" )
+insert ( 1237 1255 0 "smaller of two" )
+insert ( 1024 1255 0 "planner support for texticregexeq" )
+insert ( 1271 1255 0 "intervals overlap?" )
+insert ( 1273 1255 0 "extract field from time with time zone" )
+insert ( 1287 1255 0 "convert int8 to oid" )
+insert ( 1288 1255 0 "convert oid to int8" )
+insert ( 1291 1255 0 "trigger to suppress updates when new and old records match" )
+insert ( 1293 1255 0 "latest tid of a tuple" )
+insert ( 1294 1255 0 "latest tid of a tuple" )
+insert ( 2794 1255 0 less-equal-greater )
+insert ( 2795 1255 0 "larger of two" )
+insert ( 2796 1255 0 "smaller of two" )
+insert ( 2233 1255 0 hash )
+insert ( 2234 1255 0 hash )
+insert ( 1299 1255 0 "current transaction time" )
+insert ( 2647 1255 0 "current transaction time" )
+insert ( 2648 1255 0 "current statement time" )
+insert ( 2649 1255 0 "current clock time" )
+insert ( 1300 1255 0 "restriction selectivity for position-comparison operators" )
+insert ( 1301 1255 0 "join selectivity for position-comparison operators" )
+insert ( 1302 1255 0 "restriction selectivity for containment comparison operators" )
+insert ( 1303 1255 0 "join selectivity for containment comparison operators" )
+insert ( 1304 1255 0 "intervals overlap?" )
+insert ( 1305 1255 0 "intervals overlap?" )
+insert ( 1306 1255 0 "intervals overlap?" )
+insert ( 1307 1255 0 "intervals overlap?" )
+insert ( 1308 1255 0 "intervals overlap?" )
+insert ( 1309 1255 0 "intervals overlap?" )
+insert ( 1310 1255 0 "intervals overlap?" )
+insert ( 1311 1255 0 "intervals overlap?" )
+insert ( 1312 1255 0 "I/O" )
+insert ( 1313 1255 0 "I/O" )
+insert ( 2905 1255 0 "I/O typmod" )
+insert ( 2906 1255 0 "I/O typmod" )
+insert ( 1314 1255 0 less-equal-greater )
+insert ( 1315 1255 0 less-equal-greater )
+insert ( 1316 1255 0 "convert timestamp to time" )
+insert ( 1317 1255 0 length )
+insert ( 1318 1255 0 "character length" )
+insert ( 1339 1255 0 "base 10 logarithm" )
+insert ( 1340 1255 0 "base 10 logarithm" )
+insert ( 1194 1255 0 "base 10 logarithm" )
+insert ( 1341 1255 0 "natural logarithm" )
+insert ( 1342 1255 0 "round to nearest integer" )
+insert ( 1343 1255 0 "truncate to integer" )
+insert ( 1344 1255 0 "square root" )
+insert ( 1345 1255 0 "cube root" )
+insert ( 1346 1255 0 exponentiation )
+insert ( 1368 1255 0 exponentiation )
+insert ( 1347 1255 0 "natural exponential (e^x)" )
+insert ( 1348 1255 0 "deprecated, use two-argument form instead" )
+insert ( 1349 1255 0 "print type names of oidvector field" )
+insert ( 1350 1255 0 "I/O" )
+insert ( 1351 1255 0 "I/O" )
+insert ( 2911 1255 0 "I/O typmod" )
+insert ( 2912 1255 0 "I/O typmod" )
+insert ( 1358 1255 0 less-equal-greater )
+insert ( 1359 1255 0 "convert date and time with time zone to timestamp with time zone" )
+insert ( 1367 1255 0 "character length" )
+insert ( 1369 1255 0 "character length" )
+insert ( 1370 1255 0 "convert time to interval" )
+insert ( 1372 1255 0 "character length" )
+insert ( 1374 1255 0 "octet length" )
+insert ( 1375 1255 0 "octet length" )
+insert ( 1377 1255 0 "larger of two" )
+insert ( 1378 1255 0 "smaller of two" )
+insert ( 1379 1255 0 "larger of two" )
+insert ( 1380 1255 0 "smaller of two" )
+insert ( 1381 1255 0 "character length" )
+insert ( 1384 1255 0 "extract field from date" )
+insert ( 1385 1255 0 "extract field from time" )
+insert ( 1386 1255 0 "date difference from today preserving months and years" )
+insert ( 1388 1255 0 "convert timestamp with time zone to time with time zone" )
+insert ( 1373 1255 0 "finite date?" )
+insert ( 1389 1255 0 "finite timestamp?" )
+insert ( 1390 1255 0 "finite interval?" )
+insert ( 1376 1255 0 factorial )
+insert ( 1394 1255 0 "absolute value" )
+insert ( 1395 1255 0 "absolute value" )
+insert ( 1396 1255 0 "absolute value" )
+insert ( 1397 1255 0 "absolute value" )
+insert ( 1398 1255 0 "absolute value" )
+insert ( 1400 1255 0 "convert varchar to name" )
+insert ( 1401 1255 0 "convert name to varchar" )
+insert ( 1402 1255 0 "current schema name" )
+insert ( 1403 1255 0 "current schema search list" )
+insert ( 1404 1255 0 "substitute portion of string" )
+insert ( 1405 1255 0 "substitute portion of string" )
+insert ( 1406 1255 0 "vertically aligned" )
+insert ( 1407 1255 0 "horizontally aligned" )
+insert ( 1408 1255 0 parallel )
+insert ( 1409 1255 0 perpendicular )
+insert ( 1410 1255 0 vertical )
+insert ( 1411 1255 0 horizontal )
+insert ( 1412 1255 0 parallel )
+insert ( 1413 1255 0 perpendicular )
+insert ( 1414 1255 0 vertical )
+insert ( 1415 1255 0 horizontal )
+insert ( 1416 1255 0 "center of" )
+insert ( 1419 1255 0 "convert interval to time" )
+insert ( 1421 1255 0 "convert points to box" )
+insert ( 1430 1255 0 "path closed?" )
+insert ( 1431 1255 0 "path open?" )
+insert ( 1433 1255 0 "close path" )
+insert ( 1434 1255 0 "open path" )
+insert ( 1440 1255 0 "convert x, y to point" )
+insert ( 1446 1255 0 "convert polygon to bounding box" )
+insert ( 1447 1255 0 "convert polygon to path" )
+insert ( 1448 1255 0 "convert box to polygon" )
+insert ( 1449 1255 0 "convert path to polygon" )
+insert ( 1450 1255 0 "I/O" )
+insert ( 1451 1255 0 "I/O" )
+insert ( 1468 1255 0 "area of circle" )
+insert ( 1469 1255 0 "diameter of circle" )
+insert ( 1470 1255 0 "radius of circle" )
+insert ( 1473 1255 0 "convert point and radius to circle" )
+insert ( 1474 1255 0 "convert polygon to circle" )
+insert ( 1475 1255 0 "convert vertex count and circle to polygon" )
+insert ( 4091 1255 0 "convert point to empty box" )
+insert ( 1479 1255 0 "convert box to circle" )
+insert ( 1480 1255 0 "convert circle to box" )
+insert ( 1490 1255 0 "I/O" )
+insert ( 1491 1255 0 "I/O" )
+insert ( 1493 1255 0 "construct line from points" )
+insert ( 1530 1255 0 "distance between endpoints" )
+insert ( 1531 1255 0 "sum of path segments" )
+insert ( 1532 1255 0 "center of" )
+insert ( 1533 1255 0 "center of" )
+insert ( 1534 1255 0 "center of" )
+insert ( 1540 1255 0 "center of" )
+insert ( 1541 1255 0 "diagonal of" )
+insert ( 1542 1255 0 "center of" )
+insert ( 1543 1255 0 "center of" )
+insert ( 1544 1255 0 "convert circle to 12-vertex polygon" )
+insert ( 1545 1255 0 "number of points" )
+insert ( 1556 1255 0 "number of points" )
+insert ( 1564 1255 0 "I/O" )
+insert ( 1565 1255 0 "I/O" )
+insert ( 2919 1255 0 "I/O typmod" )
+insert ( 2920 1255 0 "I/O typmod" )
+insert ( 1569 1255 0 "matches LIKE expression" )
+insert ( 1570 1255 0 "does not match LIKE expression" )
+insert ( 1571 1255 0 "matches LIKE expression" )
+insert ( 1572 1255 0 "does not match LIKE expression" )
+insert ( 1574 1255 0 "sequence next value" )
+insert ( 1575 1255 0 "sequence current value" )
+insert ( 1576 1255 0 "set sequence value" )
+insert ( 1765 1255 0 "set sequence value and is_called status" )
+insert ( 3078 1255 0 "sequence parameters, for use by information schema" )
+insert ( 4032 1255 0 "sequence last value" )
+insert ( 275 1255 0 "return the next oid for a system table" )
+insert ( 1579 1255 0 "I/O" )
+insert ( 1580 1255 0 "I/O" )
+insert ( 2902 1255 0 "I/O typmod" )
+insert ( 2921 1255 0 "I/O typmod" )
+insert ( 1596 1255 0 less-equal-greater )
+insert ( 1598 1255 0 "random value" )
+insert ( 1599 1255 0 "set random seed" )
+insert ( 1600 1255 0 arcsine )
+insert ( 1601 1255 0 arccosine )
+insert ( 1602 1255 0 arctangent )
+insert ( 1603 1255 0 "arctangent, two arguments" )
+insert ( 1604 1255 0 sine )
+insert ( 1605 1255 0 cosine )
+insert ( 1606 1255 0 tangent )
+insert ( 1607 1255 0 cotangent )
+insert ( 2731 1255 0 "arcsine, degrees" )
+insert ( 2732 1255 0 "arccosine, degrees" )
+insert ( 2733 1255 0 "arctangent, degrees" )
+insert ( 2734 1255 0 "arctangent, two arguments, degrees" )
+insert ( 2735 1255 0 "sine, degrees" )
+insert ( 2736 1255 0 "cosine, degrees" )
+insert ( 2737 1255 0 "tangent, degrees" )
+insert ( 2738 1255 0 "cotangent, degrees" )
+insert ( 1608 1255 0 "radians to degrees" )
+insert ( 1609 1255 0 "degrees to radians" )
+insert ( 1610 1255 0 PI )
+insert ( 2462 1255 0 "hyperbolic sine" )
+insert ( 2463 1255 0 "hyperbolic cosine" )
+insert ( 2464 1255 0 "hyperbolic tangent" )
+insert ( 2465 1255 0 "inverse hyperbolic sine" )
+insert ( 2466 1255 0 "inverse hyperbolic cosine" )
+insert ( 2467 1255 0 "inverse hyperbolic tangent" )
+insert ( 1620 1255 0 "convert first char to int4" )
+insert ( 1621 1255 0 "convert int4 to char" )
+insert ( 1622 1255 0 "replicate string n times" )
+insert ( 1623 1255 0 "convert SQL regexp pattern to POSIX style" )
+insert ( 1986 1255 0 "convert SQL regexp pattern to POSIX style" )
+insert ( 1987 1255 0 "convert SQL regexp pattern to POSIX style" )
+insert ( 1025 1255 0 "planner support for texticlike" )
+insert ( 1637 1255 0 "convert LIKE pattern to use backslash escapes" )
+insert ( 868 1255 0 "position of substring" )
+insert ( 870 1255 0 lowercase )
+insert ( 871 1255 0 uppercase )
+insert ( 872 1255 0 "capitalize each word" )
+insert ( 873 1255 0 "left-pad string to length" )
+insert ( 874 1255 0 "right-pad string to length" )
+insert ( 875 1255 0 "trim selected characters from left end of string" )
+insert ( 876 1255 0 "trim selected characters from right end of string" )
+insert ( 877 1255 0 "extract portion of string" )
+insert ( 878 1255 0 "map a set of characters appearing in string" )
+insert ( 879 1255 0 "left-pad string to length" )
+insert ( 880 1255 0 "right-pad string to length" )
+insert ( 881 1255 0 "trim spaces from left end of string" )
+insert ( 882 1255 0 "trim spaces from right end of string" )
+insert ( 883 1255 0 "extract portion of string" )
+insert ( 884 1255 0 "trim selected characters from both ends of string" )
+insert ( 885 1255 0 "trim spaces from both ends of string" )
+insert ( 936 1255 0 "extract portion of string" )
+insert ( 937 1255 0 "extract portion of string" )
+insert ( 2087 1255 0 "replace all occurrences in string of old_substr with new_substr" )
+insert ( 2284 1255 0 "replace text using regexp" )
+insert ( 2285 1255 0 "replace text using regexp" )
+insert ( 3396 1255 0 "find first match for regexp" )
+insert ( 3397 1255 0 "find first match for regexp" )
+insert ( 2763 1255 0 "find match(es) for regexp" )
+insert ( 2764 1255 0 "find match(es) for regexp" )
+insert ( 2088 1255 0 "split string by field_sep and return field_num" )
+insert ( 2765 1255 0 "split string by pattern" )
+insert ( 2766 1255 0 "split string by pattern" )
+insert ( 2767 1255 0 "split string by pattern" )
+insert ( 2768 1255 0 "split string by pattern" )
+insert ( 2089 1255 0 "convert int4 number to hex" )
+insert ( 2090 1255 0 "convert int8 number to hex" )
+insert ( 1039 1255 0 "encoding name of current database" )
+insert ( 810 1255 0 "encoding name of current database" )
+insert ( 1713 1255 0 "length of string in specified encoding" )
+insert ( 1714 1255 0 "convert string with specified source encoding name" )
+insert ( 1717 1255 0 "convert string with specified destination encoding name" )
+insert ( 1813 1255 0 "convert string with specified encoding names" )
+insert ( 1264 1255 0 "convert encoding name to encoding id" )
+insert ( 1597 1255 0 "convert encoding id to encoding name" )
+insert ( 2319 1255 0 "maximum octet length of a character in given encoding" )
+insert ( 1573 1255 0 "source text of a rule" )
+insert ( 1640 1255 0 "select statement of a view" )
+insert ( 1641 1255 0 "select statement of a view" )
+insert ( 1642 1255 0 "role name by OID (with fallback)" )
+insert ( 1643 1255 0 "index description" )
+insert ( 3415 1255 0 "extended statistics object description" )
+insert ( 3352 1255 0 "partition key description" )
+insert ( 3408 1255 0 "partition constraint description" )
+insert ( 1662 1255 0 "trigger description" )
+insert ( 1387 1255 0 "constraint description" )
+insert ( 1716 1255 0 "deparse an encoded expression" )
+insert ( 1665 1255 0 "name of sequence for a serial column" )
+insert ( 2098 1255 0 "definition of a function" )
+insert ( 2162 1255 0 "argument list of a function" )
+insert ( 2232 1255 0 "identity argument list of a function" )
+insert ( 2165 1255 0 "result type of a function" )
+insert ( 3808 1255 0 "function argument default" )
+insert ( 1686 1255 0 "list of SQL keywords" )
+insert ( 2289 1255 0 "convert generic options array to name/value table" )
+insert ( 1619 1255 0 "type of the argument" )
+insert ( 3162 1255 0 "collation of the argument; implementation of the COLLATION FOR expression" )
+insert ( 3842 1255 0 "is a relation insertable/updatable/deletable" )
+insert ( 3843 1255 0 "is a column updatable" )
+insert ( 6120 1255 0 "oid of replica identity index if any" )
+insert ( 1250 1255 0 "deferred UNIQUE constraint check" )
+insert ( 1644 1255 0 "referential integrity FOREIGN KEY ... REFERENCES" )
+insert ( 1645 1255 0 "referential integrity FOREIGN KEY ... REFERENCES" )
+insert ( 1646 1255 0 "referential integrity ON DELETE CASCADE" )
+insert ( 1647 1255 0 "referential integrity ON UPDATE CASCADE" )
+insert ( 1648 1255 0 "referential integrity ON DELETE RESTRICT" )
+insert ( 1649 1255 0 "referential integrity ON UPDATE RESTRICT" )
+insert ( 1650 1255 0 "referential integrity ON DELETE SET NULL" )
+insert ( 1651 1255 0 "referential integrity ON UPDATE SET NULL" )
+insert ( 1652 1255 0 "referential integrity ON DELETE SET DEFAULT" )
+insert ( 1653 1255 0 "referential integrity ON UPDATE SET DEFAULT" )
+insert ( 1654 1255 0 "referential integrity ON DELETE NO ACTION" )
+insert ( 1655 1255 0 "referential integrity ON UPDATE NO ACTION" )
+insert ( 1672 1255 0 less-equal-greater )
+insert ( 1680 1255 0 "extract portion of bitstring" )
+insert ( 1681 1255 0 "bitstring length" )
+insert ( 1682 1255 0 "octet length" )
+insert ( 1683 1255 0 "convert int4 to bitstring" )
+insert ( 1684 1255 0 "convert bitstring to int4" )
+insert ( 1685 1255 0 "adjust bit() to typmod length" )
+insert ( 3158 1255 0 "planner support for varbit length coercion" )
+insert ( 1687 1255 0 "adjust varbit() to typmod length" )
+insert ( 1698 1255 0 "position of sub-bitstring" )
+insert ( 1699 1255 0 "extract portion of bitstring" )
+insert ( 3030 1255 0 "substitute portion of bitstring" )
+insert ( 3031 1255 0 "substitute portion of bitstring" )
+insert ( 3032 1255 0 "get bit" )
+insert ( 3033 1255 0 "set bit" )
+insert ( 436 1255 0 "I/O" )
+insert ( 437 1255 0 "I/O" )
+insert ( 753 1255 0 "MACADDR manufacturer fields" )
+insert ( 836 1255 0 less-equal-greater )
+insert ( 3359 1255 0 "sort support" )
+insert ( 4110 1255 0 "I/O" )
+insert ( 4111 1255 0 "I/O" )
+insert ( 4112 1255 0 "MACADDR8 manufacturer fields" )
+insert ( 4119 1255 0 less-equal-greater )
+insert ( 4123 1255 0 "convert macaddr to macaddr8" )
+insert ( 4124 1255 0 "convert macaddr8 to macaddr" )
+insert ( 4125 1255 0 "set 7th bit in macaddr8" )
+insert ( 910 1255 0 "I/O" )
+insert ( 911 1255 0 "I/O" )
+insert ( 1267 1255 0 "I/O" )
+insert ( 1427 1255 0 "I/O" )
+insert ( 3562 1255 0 "larger of two" )
+insert ( 3563 1255 0 "smaller of two" )
+insert ( 926 1255 0 less-equal-greater )
+insert ( 1173 1255 0 "planner support for network_sub/superset" )
+insert ( 5033 1255 0 "sort support" )
+insert ( 598 1255 0 "abbreviated display of inet value" )
+insert ( 599 1255 0 "abbreviated display of cidr value" )
+insert ( 605 1255 0 "change netmask of inet" )
+insert ( 635 1255 0 "change netmask of cidr" )
+insert ( 711 1255 0 "address family (4 for IPv4, 6 for IPv6)" )
+insert ( 683 1255 0 "network part of address" )
+insert ( 696 1255 0 "netmask of address" )
+insert ( 697 1255 0 "netmask length" )
+insert ( 698 1255 0 "broadcast address of network" )
+insert ( 699 1255 0 "show address octets only" )
+insert ( 730 1255 0 "show all parts of inet/cidr value" )
+insert ( 1362 1255 0 "hostmask of address" )
+insert ( 1715 1255 0 "convert inet to cidr" )
+insert ( 2196 1255 0 "inet address of the client" )
+insert ( 2197 1255 0 "client''s port number for this connection" )
+insert ( 2198 1255 0 "inet address of the server" )
+insert ( 2199 1255 0 "server''s port number for this connection" )
+insert ( 4071 1255 0 "are the addresses from the same family?" )
+insert ( 4063 1255 0 "the smallest network which includes both of the given networks" )
+insert ( 3553 1255 0 "GiST support" )
+insert ( 3554 1255 0 "GiST support" )
+insert ( 3555 1255 0 "GiST support" )
+insert ( 3573 1255 0 "GiST support" )
+insert ( 3557 1255 0 "GiST support" )
+insert ( 3558 1255 0 "GiST support" )
+insert ( 3559 1255 0 "GiST support" )
+insert ( 3795 1255 0 "SP-GiST support" )
+insert ( 3796 1255 0 "SP-GiST support" )
+insert ( 3797 1255 0 "SP-GiST support" )
+insert ( 3798 1255 0 "SP-GiST support" )
+insert ( 3799 1255 0 "SP-GiST support" )
+insert ( 3560 1255 0 "restriction selectivity for network operators" )
+insert ( 3561 1255 0 "join selectivity for network operators" )
+insert ( 1693 1255 0 less-equal-greater )
+insert ( 1688 1255 0 hash )
+insert ( 3409 1255 0 hash )
+insert ( 1696 1255 0 hash )
+insert ( 3410 1255 0 hash )
+insert ( 1697 1255 0 hash )
+insert ( 3418 1255 0 hash )
+insert ( 1701 1255 0 "I/O" )
+insert ( 1702 1255 0 "I/O" )
+insert ( 2917 1255 0 "I/O typmod" )
+insert ( 2918 1255 0 "I/O typmod" )
+insert ( 3157 1255 0 "planner support for numeric length coercion" )
+insert ( 1703 1255 0 "adjust numeric to typmod precision/scale" )
+insert ( 1705 1255 0 "absolute value" )
+insert ( 1706 1255 0 "sign of value" )
+insert ( 1707 1255 0 "value rounded to ''scale''" )
+insert ( 1708 1255 0 "value rounded to ''scale'' of zero" )
+insert ( 1709 1255 0 "value truncated to ''scale''" )
+insert ( 1710 1255 0 "value truncated to ''scale'' of zero" )
+insert ( 1711 1255 0 "nearest integer >= value" )
+insert ( 2167 1255 0 "nearest integer >= value" )
+insert ( 1712 1255 0 "nearest integer <= value" )
+insert ( 1728 1255 0 modulus )
+insert ( 5048 1255 0 "greatest common divisor" )
+insert ( 5049 1255 0 "least common multiple" )
+insert ( 1730 1255 0 "square root" )
+insert ( 1731 1255 0 "square root" )
+insert ( 1732 1255 0 "natural exponential (e^x)" )
+insert ( 1733 1255 0 "natural exponential (e^x)" )
+insert ( 1734 1255 0 "natural logarithm" )
+insert ( 1735 1255 0 "natural logarithm" )
+insert ( 1736 1255 0 "logarithm base m of n" )
+insert ( 1737 1255 0 "logarithm base m of n" )
+insert ( 1738 1255 0 exponentiation )
+insert ( 2169 1255 0 exponentiation )
+insert ( 3281 1255 0 "number of decimal digits in the fractional part" )
+insert ( 5042 1255 0 "minimum scale needed to represent the value" )
+insert ( 5043 1255 0 "numeric with minimum scale needed to represent the value" )
+insert ( 1740 1255 0 "convert int4 to numeric" )
+insert ( 1741 1255 0 "base 10 logarithm" )
+insert ( 1481 1255 0 "base 10 logarithm" )
+insert ( 1742 1255 0 "convert float4 to numeric" )
+insert ( 1743 1255 0 "convert float8 to numeric" )
+insert ( 1744 1255 0 "convert numeric to int4" )
+insert ( 1745 1255 0 "convert numeric to float4" )
+insert ( 1746 1255 0 "convert numeric to float8" )
+insert ( 1973 1255 0 "trunc(x/y)" )
+insert ( 1980 1255 0 "trunc(x/y)" )
+insert ( 2170 1255 0 "bucket number of operand in equal-width histogram" )
+insert ( 1764 1255 0 "increment by one" )
+insert ( 1766 1255 0 "smaller of two" )
+insert ( 1767 1255 0 "larger of two" )
+insert ( 1769 1255 0 less-equal-greater )
+insert ( 3283 1255 0 "sort support" )
+insert ( 1779 1255 0 "convert numeric to int8" )
+insert ( 1781 1255 0 "convert int8 to numeric" )
+insert ( 1782 1255 0 "convert int2 to numeric" )
+insert ( 1783 1255 0 "convert numeric to int2" )
+insert ( 3556 1255 0 "convert jsonb to boolean" )
+insert ( 3449 1255 0 "convert jsonb to numeric" )
+insert ( 3450 1255 0 "convert jsonb to int2" )
+insert ( 3451 1255 0 "convert jsonb to int4" )
+insert ( 3452 1255 0 "convert jsonb to int8" )
+insert ( 3453 1255 0 "convert jsonb to float4" )
+insert ( 2580 1255 0 "convert jsonb to float8" )
+insert ( 1770 1255 0 "format timestamp with time zone to text" )
+insert ( 1772 1255 0 "format numeric to text" )
+insert ( 1773 1255 0 "format int4 to text" )
+insert ( 1774 1255 0 "format int8 to text" )
+insert ( 1775 1255 0 "format float4 to text" )
+insert ( 1776 1255 0 "format float8 to text" )
+insert ( 1777 1255 0 "convert text to numeric" )
+insert ( 1778 1255 0 "convert text to timestamp with time zone" )
+insert ( 1780 1255 0 "convert text to date" )
+insert ( 1768 1255 0 "format interval to text" )
+insert ( 1282 1255 0 "quote an identifier for usage in a querystring" )
+insert ( 1283 1255 0 "quote a literal for usage in a querystring" )
+insert ( 1285 1255 0 "quote a data value for usage in a querystring" )
+insert ( 1289 1255 0 "quote a possibly-null literal for usage in a querystring" )
+insert ( 1290 1255 0 "quote a possibly-null data value for usage in a querystring" )
+insert ( 1798 1255 0 "I/O" )
+insert ( 1799 1255 0 "I/O" )
+insert ( 3058 1255 0 "concatenate values" )
+insert ( 3059 1255 0 "concatenate values with separators" )
+insert ( 3060 1255 0 "extract the first n characters" )
+insert ( 3061 1255 0 "extract the last n characters" )
+insert ( 3062 1255 0 "reverse text" )
+insert ( 3539 1255 0 "format text message" )
+insert ( 3540 1255 0 "format text message" )
+insert ( 1810 1255 0 "length in bits" )
+insert ( 1811 1255 0 "length in bits" )
+insert ( 1812 1255 0 "length in bits" )
+insert ( 1814 1255 0 "restriction selectivity of ILIKE" )
+insert ( 1815 1255 0 "restriction selectivity of NOT ILIKE" )
+insert ( 1816 1255 0 "join selectivity of ILIKE" )
+insert ( 1817 1255 0 "join selectivity of NOT ILIKE" )
+insert ( 1818 1255 0 "restriction selectivity of regex match" )
+insert ( 1819 1255 0 "restriction selectivity of LIKE" )
+insert ( 1820 1255 0 "restriction selectivity of case-insensitive regex match" )
+insert ( 1821 1255 0 "restriction selectivity of regex non-match" )
+insert ( 1822 1255 0 "restriction selectivity of NOT LIKE" )
+insert ( 1823 1255 0 "restriction selectivity of case-insensitive regex non-match" )
+insert ( 1824 1255 0 "join selectivity of regex match" )
+insert ( 1825 1255 0 "join selectivity of LIKE" )
+insert ( 1826 1255 0 "join selectivity of case-insensitive regex match" )
+insert ( 1827 1255 0 "join selectivity of regex non-match" )
+insert ( 1828 1255 0 "join selectivity of NOT LIKE" )
+insert ( 1829 1255 0 "join selectivity of case-insensitive regex non-match" )
+insert ( 3437 1255 0 "restriction selectivity of exact prefix" )
+insert ( 3438 1255 0 "join selectivity of exact prefix" )
+insert ( 1830 1255 0 "aggregate final function" )
+insert ( 2512 1255 0 "aggregate final function" )
+insert ( 1831 1255 0 "aggregate final function" )
+insert ( 2513 1255 0 "aggregate final function" )
+insert ( 1832 1255 0 "aggregate final function" )
+insert ( 1833 1255 0 "aggregate transition function" )
+insert ( 3341 1255 0 "aggregate combine function" )
+insert ( 2858 1255 0 "aggregate transition function" )
+insert ( 3337 1255 0 "aggregate combine function" )
+insert ( 2740 1255 0 "aggregate serial function" )
+insert ( 2741 1255 0 "aggregate deserial function" )
+insert ( 3335 1255 0 "aggregate serial function" )
+insert ( 3336 1255 0 "aggregate deserial function" )
+insert ( 3548 1255 0 "aggregate transition function" )
+insert ( 1834 1255 0 "aggregate transition function" )
+insert ( 1835 1255 0 "aggregate transition function" )
+insert ( 1836 1255 0 "aggregate transition function" )
+insert ( 3338 1255 0 "aggregate combine function" )
+insert ( 3339 1255 0 "aggregate serial function" )
+insert ( 3340 1255 0 "aggregate deserial function" )
+insert ( 2746 1255 0 "aggregate transition function" )
+insert ( 3567 1255 0 "aggregate transition function" )
+insert ( 3568 1255 0 "aggregate transition function" )
+insert ( 3569 1255 0 "aggregate transition function" )
+insert ( 3387 1255 0 "aggregate transition function" )
+insert ( 2785 1255 0 "aggregate combine function" )
+insert ( 2786 1255 0 "aggregate serial function" )
+insert ( 2787 1255 0 "aggregate deserial function" )
+insert ( 3324 1255 0 "aggregate combine function" )
+insert ( 3178 1255 0 "aggregate final function" )
+insert ( 1837 1255 0 "aggregate final function" )
+insert ( 2514 1255 0 "aggregate final function" )
+insert ( 1838 1255 0 "aggregate final function" )
+insert ( 2596 1255 0 "aggregate final function" )
+insert ( 1839 1255 0 "aggregate final function" )
+insert ( 1840 1255 0 "aggregate transition function" )
+insert ( 1841 1255 0 "aggregate transition function" )
+insert ( 1842 1255 0 "aggregate transition function" )
+insert ( 3388 1255 0 "aggregate final function" )
+insert ( 3389 1255 0 "aggregate final function" )
+insert ( 3390 1255 0 "aggregate final function" )
+insert ( 3391 1255 0 "aggregate final function" )
+insert ( 3392 1255 0 "aggregate final function" )
+insert ( 3393 1255 0 "aggregate final function" )
+insert ( 1843 1255 0 "aggregate transition function" )
+insert ( 3325 1255 0 "aggregate combine function" )
+insert ( 3549 1255 0 "aggregate transition function" )
+insert ( 1844 1255 0 "aggregate final function" )
+insert ( 1962 1255 0 "aggregate transition function" )
+insert ( 1963 1255 0 "aggregate transition function" )
+insert ( 3570 1255 0 "aggregate transition function" )
+insert ( 3571 1255 0 "aggregate transition function" )
+insert ( 1964 1255 0 "aggregate final function" )
+insert ( 3572 1255 0 "aggregate final function" )
+insert ( 2805 1255 0 "aggregate transition function" )
+insert ( 2806 1255 0 "aggregate transition function" )
+insert ( 3342 1255 0 "aggregate combine function" )
+insert ( 2807 1255 0 "aggregate final function" )
+insert ( 2808 1255 0 "aggregate final function" )
+insert ( 2809 1255 0 "aggregate final function" )
+insert ( 2810 1255 0 "aggregate final function" )
+insert ( 2811 1255 0 "aggregate final function" )
+insert ( 2812 1255 0 "aggregate final function" )
+insert ( 2813 1255 0 "aggregate final function" )
+insert ( 2814 1255 0 "aggregate final function" )
+insert ( 2815 1255 0 "aggregate final function" )
+insert ( 2816 1255 0 "aggregate final function" )
+insert ( 2817 1255 0 "aggregate final function" )
+insert ( 3535 1255 0 "aggregate transition function" )
+insert ( 3536 1255 0 "aggregate final function" )
+insert ( 3538 1255 0 "concatenate aggregate input into a string" )
+insert ( 3543 1255 0 "aggregate transition function" )
+insert ( 3544 1255 0 "aggregate final function" )
+insert ( 3545 1255 0 "concatenate aggregate input into a bytea" )
+insert ( 1845 1255 0 "encode text from DB encoding to ASCII text" )
+insert ( 1846 1255 0 "encode text from encoding to ASCII text" )
+insert ( 1847 1255 0 "encode text from encoding to ASCII text" )
+insert ( 1922 1255 0 "user privilege on relation by username, rel name" )
+insert ( 1923 1255 0 "user privilege on relation by username, rel oid" )
+insert ( 1924 1255 0 "user privilege on relation by user oid, rel name" )
+insert ( 1925 1255 0 "user privilege on relation by user oid, rel oid" )
+insert ( 1926 1255 0 "current user privilege on relation by rel name" )
+insert ( 1927 1255 0 "current user privilege on relation by rel oid" )
+insert ( 2181 1255 0 "user privilege on sequence by username, seq name" )
+insert ( 2182 1255 0 "user privilege on sequence by username, seq oid" )
+insert ( 2183 1255 0 "user privilege on sequence by user oid, seq name" )
+insert ( 2184 1255 0 "user privilege on sequence by user oid, seq oid" )
+insert ( 2185 1255 0 "current user privilege on sequence by seq name" )
+insert ( 2186 1255 0 "current user privilege on sequence by seq oid" )
+insert ( 3012 1255 0 "user privilege on column by username, rel name, col name" )
+insert ( 3013 1255 0 "user privilege on column by username, rel name, col attnum" )
+insert ( 3014 1255 0 "user privilege on column by username, rel oid, col name" )
+insert ( 3015 1255 0 "user privilege on column by username, rel oid, col attnum" )
+insert ( 3016 1255 0 "user privilege on column by user oid, rel name, col name" )
+insert ( 3017 1255 0 "user privilege on column by user oid, rel name, col attnum" )
+insert ( 3018 1255 0 "user privilege on column by user oid, rel oid, col name" )
+insert ( 3019 1255 0 "user privilege on column by user oid, rel oid, col attnum" )
+insert ( 3020 1255 0 "current user privilege on column by rel name, col name" )
+insert ( 3021 1255 0 "current user privilege on column by rel name, col attnum" )
+insert ( 3022 1255 0 "current user privilege on column by rel oid, col name" )
+insert ( 3023 1255 0 "current user privilege on column by rel oid, col attnum" )
+insert ( 3024 1255 0 "user privilege on any column by username, rel name" )
+insert ( 3025 1255 0 "user privilege on any column by username, rel oid" )
+insert ( 3026 1255 0 "user privilege on any column by user oid, rel name" )
+insert ( 3027 1255 0 "user privilege on any column by user oid, rel oid" )
+insert ( 3028 1255 0 "current user privilege on any column by rel name" )
+insert ( 3029 1255 0 "current user privilege on any column by rel oid" )
+insert ( 3355 1255 0 "I/O" )
+insert ( 3356 1255 0 "I/O" )
+insert ( 3357 1255 0 "I/O" )
+insert ( 3358 1255 0 "I/O" )
+insert ( 3404 1255 0 "I/O" )
+insert ( 3405 1255 0 "I/O" )
+insert ( 3406 1255 0 "I/O" )
+insert ( 3407 1255 0 "I/O" )
+insert ( 5018 1255 0 "I/O" )
+insert ( 5019 1255 0 "I/O" )
+insert ( 5020 1255 0 "I/O" )
+insert ( 5021 1255 0 "I/O" )
+insert ( 3427 1255 0 "details about MCV list items" )
+insert ( 1928 1255 0 "statistics: number of scans done for table/index" )
+insert ( 1929 1255 0 "statistics: number of tuples read by seqscan" )
+insert ( 1930 1255 0 "statistics: number of tuples fetched by idxscan" )
+insert ( 1931 1255 0 "statistics: number of tuples inserted" )
+insert ( 1932 1255 0 "statistics: number of tuples updated" )
+insert ( 1933 1255 0 "statistics: number of tuples deleted" )
+insert ( 1972 1255 0 "statistics: number of tuples hot updated" )
+insert ( 2878 1255 0 "statistics: number of live tuples" )
+insert ( 2879 1255 0 "statistics: number of dead tuples" )
+insert ( 3177 1255 0 "statistics: number of tuples changed since last analyze" )
+insert ( 5053 1255 0 "statistics: number of tuples inserted since last vacuum" )
+insert ( 1934 1255 0 "statistics: number of blocks fetched" )
+insert ( 1935 1255 0 "statistics: number of blocks found in cache" )
+insert ( 2781 1255 0 "statistics: last manual vacuum time for a table" )
+insert ( 2782 1255 0 "statistics: last auto vacuum time for a table" )
+insert ( 2783 1255 0 "statistics: last manual analyze time for a table" )
+insert ( 2784 1255 0 "statistics: last auto analyze time for a table" )
+insert ( 3054 1255 0 "statistics: number of manual vacuums for a table" )
+insert ( 3055 1255 0 "statistics: number of auto vacuums for a table" )
+insert ( 3056 1255 0 "statistics: number of manual analyzes for a table" )
+insert ( 3057 1255 0 "statistics: number of auto analyzes for a table" )
+insert ( 1936 1255 0 "statistics: currently active backend IDs" )
+insert ( 2022 1255 0 "statistics: information about currently active backends" )
+insert ( 3318 1255 0 "statistics: information about progress of backends running maintenance command" )
+insert ( 3099 1255 0 "statistics: information about currently active replication" )
+insert ( 3317 1255 0 "statistics: information about WAL receiver" )
+insert ( 6118 1255 0 "statistics: information about subscription" )
+insert ( 2026 1255 0 "statistics: current backend PID" )
+insert ( 1937 1255 0 "statistics: PID of backend" )
+insert ( 1938 1255 0 "statistics: database ID of backend" )
+insert ( 1939 1255 0 "statistics: user ID of backend" )
+insert ( 1940 1255 0 "statistics: current query of backend" )
+insert ( 2788 1255 0 "statistics: wait event type on which backend is currently waiting" )
+insert ( 2853 1255 0 "statistics: wait event on which backend is currently waiting" )
+insert ( 2094 1255 0 "statistics: start time for current query of backend" )
+insert ( 2857 1255 0 "statistics: start time for backend''s current transaction" )
+insert ( 1391 1255 0 "statistics: start time for current backend session" )
+insert ( 1392 1255 0 "statistics: address of client connected to backend" )
+insert ( 1393 1255 0 "statistics: port number of client connected to backend" )
+insert ( 1941 1255 0 "statistics: number of backends in database" )
+insert ( 1942 1255 0 "statistics: transactions committed" )
+insert ( 1943 1255 0 "statistics: transactions rolled back" )
+insert ( 1944 1255 0 "statistics: blocks fetched for database" )
+insert ( 1945 1255 0 "statistics: blocks found in cache for database" )
+insert ( 2758 1255 0 "statistics: tuples returned for database" )
+insert ( 2759 1255 0 "statistics: tuples fetched for database" )
+insert ( 2760 1255 0 "statistics: tuples inserted in database" )
+insert ( 2761 1255 0 "statistics: tuples updated in database" )
+insert ( 2762 1255 0 "statistics: tuples deleted in database" )
+insert ( 3065 1255 0 "statistics: recovery conflicts in database caused by drop tablespace" )
+insert ( 3066 1255 0 "statistics: recovery conflicts in database caused by relation lock" )
+insert ( 3067 1255 0 "statistics: recovery conflicts in database caused by snapshot expiry" )
+insert ( 3068 1255 0 "statistics: recovery conflicts in database caused by shared buffer pin" )
+insert ( 3069 1255 0 "statistics: recovery conflicts in database caused by buffer deadlock" )
+insert ( 3070 1255 0 "statistics: recovery conflicts in database" )
+insert ( 3152 1255 0 "statistics: deadlocks detected in database" )
+insert ( 3426 1255 0 "statistics: checksum failures detected in database" )
+insert ( 3428 1255 0 "statistics: when last checksum failure was detected in database" )
+insert ( 3074 1255 0 "statistics: last reset for a database" )
+insert ( 3150 1255 0 "statistics: number of temporary files written" )
+insert ( 3151 1255 0 "statistics: number of bytes in temporary files written" )
+insert ( 2844 1255 0 "statistics: block read time, in milliseconds" )
+insert ( 2845 1255 0 "statistics: block write time, in milliseconds" )
+insert ( 3195 1255 0 "statistics: information about WAL archiver" )
+insert ( 2769 1255 0 "statistics: number of timed checkpoints started by the bgwriter" )
+insert ( 2770 1255 0 "statistics: number of backend requested checkpoints started by the bgwriter" )
+insert ( 2771 1255 0 "statistics: number of buffers written by the bgwriter during checkpoints" )
+insert ( 2772 1255 0 "statistics: number of buffers written by the bgwriter for cleaning dirty buffers" )
+insert ( 2773 1255 0 "statistics: number of times the bgwriter stopped processing when it had written too many buffers while cleaning" )
+insert ( 3075 1255 0 "statistics: last reset for the bgwriter" )
+insert ( 3160 1255 0 "statistics: checkpoint time spent writing buffers to disk, in milliseconds" )
+insert ( 3161 1255 0 "statistics: checkpoint time spent synchronizing buffers to disk, in milliseconds" )
+insert ( 2775 1255 0 "statistics: number of buffers written by backends" )
+insert ( 3063 1255 0 "statistics: number of backend buffer writes that did their own fsync" )
+insert ( 2859 1255 0 "statistics: number of buffer allocations" )
+insert ( 2306 1255 0 "statistics: information about SLRU caches" )
+insert ( 2978 1255 0 "statistics: number of function calls" )
+insert ( 2979 1255 0 "statistics: total execution time of function, in milliseconds" )
+insert ( 2980 1255 0 "statistics: self execution time of function, in milliseconds" )
+insert ( 3037 1255 0 "statistics: number of scans done for table/index in current transaction" )
+insert ( 3038 1255 0 "statistics: number of tuples read by seqscan in current transaction" )
+insert ( 3039 1255 0 "statistics: number of tuples fetched by idxscan in current transaction" )
+insert ( 3040 1255 0 "statistics: number of tuples inserted in current transaction" )
+insert ( 3041 1255 0 "statistics: number of tuples updated in current transaction" )
+insert ( 3042 1255 0 "statistics: number of tuples deleted in current transaction" )
+insert ( 3043 1255 0 "statistics: number of tuples hot updated in current transaction" )
+insert ( 3044 1255 0 "statistics: number of blocks fetched in current transaction" )
+insert ( 3045 1255 0 "statistics: number of blocks found in cache in current transaction" )
+insert ( 3046 1255 0 "statistics: number of function calls in current transaction" )
+insert ( 3047 1255 0 "statistics: total execution time of function in current transaction, in milliseconds" )
+insert ( 3048 1255 0 "statistics: self execution time of function in current transaction, in milliseconds" )
+insert ( 3788 1255 0 "statistics: timestamp of the current statistics snapshot" )
+insert ( 2230 1255 0 "statistics: discard current transaction''s statistics snapshot" )
+insert ( 2274 1255 0 "statistics: reset collected statistics for current database" )
+insert ( 3775 1255 0 "statistics: reset collected statistics shared across the cluster" )
+insert ( 3776 1255 0 "statistics: reset collected statistics for a single table or index in the current database" )
+insert ( 3777 1255 0 "statistics: reset collected statistics for a single function in the current database" )
+insert ( 2307 1255 0 "statistics: reset collected statistics for a single SLRU" )
+insert ( 3163 1255 0 "current trigger depth" )
+insert ( 3778 1255 0 "tablespace location" )
+insert ( 1946 1255 0 "convert bytea value into some ascii-only text string" )
+insert ( 1947 1255 0 "convert ascii-encoded text string into bytea value" )
+insert ( 1954 1255 0 less-equal-greater )
+insert ( 3331 1255 0 "sort support" )
+insert ( 3917 1255 0 "planner support for timestamp length coercion" )
+insert ( 3944 1255 0 "planner support for time length coercion" )
+insert ( 1961 1255 0 "adjust timestamp precision" )
+insert ( 1965 1255 0 "larger of two" )
+insert ( 1966 1255 0 "smaller of two" )
+insert ( 1967 1255 0 "adjust timestamptz precision" )
+insert ( 1968 1255 0 "adjust time precision" )
+insert ( 1969 1255 0 "adjust time with time zone precision" )
+insert ( 2007 1255 0 "matches LIKE expression" )
+insert ( 2008 1255 0 "does not match LIKE expression" )
+insert ( 2009 1255 0 "convert LIKE pattern to use backslash escapes" )
+insert ( 2010 1255 0 "octet length" )
+insert ( 2012 1255 0 "extract portion of string" )
+insert ( 2013 1255 0 "extract portion of string" )
+insert ( 2085 1255 0 "extract portion of string" )
+insert ( 2086 1255 0 "extract portion of string" )
+insert ( 2014 1255 0 "position of substring" )
+insert ( 2015 1255 0 "trim both ends of string" )
+insert ( 2019 1255 0 "convert timestamp with time zone to time" )
+insert ( 2020 1255 0 "truncate timestamp to specified units" )
+insert ( 2021 1255 0 "extract field from timestamp" )
+insert ( 2024 1255 0 "convert date to timestamp" )
+insert ( 2025 1255 0 "convert date and time to timestamp" )
+insert ( 2027 1255 0 "convert timestamp with time zone to timestamp" )
+insert ( 2028 1255 0 "convert timestamp to timestamp with time zone" )
+insert ( 2029 1255 0 "convert timestamp to date" )
+insert ( 2035 1255 0 "smaller of two" )
+insert ( 2036 1255 0 "larger of two" )
+insert ( 2037 1255 0 "adjust time with time zone to new zone" )
+insert ( 2038 1255 0 "adjust time with time zone to new zone" )
+insert ( 2039 1255 0 hash )
+insert ( 3411 1255 0 hash )
+insert ( 2041 1255 0 "intervals overlap?" )
+insert ( 2042 1255 0 "intervals overlap?" )
+insert ( 2043 1255 0 "intervals overlap?" )
+insert ( 2044 1255 0 "intervals overlap?" )
+insert ( 2045 1255 0 less-equal-greater )
+insert ( 3137 1255 0 "sort support" )
+insert ( 4134 1255 0 "window RANGE support" )
+insert ( 4135 1255 0 "window RANGE support" )
+insert ( 4136 1255 0 "window RANGE support" )
+insert ( 4137 1255 0 "window RANGE support" )
+insert ( 4138 1255 0 "window RANGE support" )
+insert ( 2046 1255 0 "convert time with time zone to time" )
+insert ( 2047 1255 0 "convert time to time with time zone" )
+insert ( 2048 1255 0 "finite timestamp?" )
+insert ( 2049 1255 0 "format timestamp to text" )
+insert ( 2058 1255 0 "date difference preserving months and years" )
+insert ( 2059 1255 0 "date difference from today preserving months and years" )
+insert ( 2069 1255 0 "adjust timestamp to new time zone" )
+insert ( 2070 1255 0 "adjust timestamp to new time zone" )
+insert ( 2073 1255 0 "extract text matching regular expression" )
+insert ( 2074 1255 0 "extract text matching SQL regular expression" )
+insert ( 2075 1255 0 "convert int8 to bitstring" )
+insert ( 2076 1255 0 "convert bitstring to int8" )
+insert ( 2077 1255 0 "SHOW X as a function" )
+insert ( 3294 1255 0 "SHOW X as a function, optionally no error for missing variable" )
+insert ( 2078 1255 0 "SET X as a function" )
+insert ( 2084 1255 0 "SHOW ALL as a function" )
+insert ( 3329 1255 0 "show config file settings" )
+insert ( 3401 1255 0 "show pg_hba.conf rules" )
+insert ( 1371 1255 0 "view system lock information" )
+insert ( 2561 1255 0 "get array of PIDs of sessions blocking specified backend PID from acquiring a heavyweight lock" )
+insert ( 3376 1255 0 "get array of PIDs of sessions blocking specified backend PID from acquiring a safe snapshot" )
+insert ( 3378 1255 0 "isolationtester support function" )
+insert ( 1065 1255 0 "view two-phase transactions" )
+insert ( 3819 1255 0 "view members of a multixactid" )
+insert ( 3581 1255 0 "get commit timestamp of a transaction" )
+insert ( 3583 1255 0 "get transaction Id and commit timestamp of latest transaction commit" )
+insert ( 3537 1255 0 "get identification of SQL object" )
+insert ( 3839 1255 0 "get machine-parseable identification of SQL object" )
+insert ( 3382 1255 0 "get identification of SQL object for pg_get_object_address()" )
+insert ( 3954 1255 0 "get OID-based object address from name/args arrays" )
+insert ( 2079 1255 0 "is table visible in search path?" )
+insert ( 2080 1255 0 "is type visible in search path?" )
+insert ( 2081 1255 0 "is function visible in search path?" )
+insert ( 2082 1255 0 "is operator visible in search path?" )
+insert ( 2083 1255 0 "is opclass visible in search path?" )
+insert ( 3829 1255 0 "is opfamily visible in search path?" )
+insert ( 2093 1255 0 "is conversion visible in search path?" )
+insert ( 3403 1255 0 "is statistics object visible in search path?" )
+insert ( 3756 1255 0 "is text search parser visible in search path?" )
+insert ( 3757 1255 0 "is text search dictionary visible in search path?" )
+insert ( 3768 1255 0 "is text search template visible in search path?" )
+insert ( 3758 1255 0 "is text search configuration visible in search path?" )
+insert ( 3815 1255 0 "is collation visible in search path?" )
+insert ( 2854 1255 0 "get OID of current session''s temp schema, if any" )
+insert ( 2855 1255 0 "is schema another session''s temp schema?" )
+insert ( 2171 1255 0 "cancel a server process'' current query" )
+insert ( 2096 1255 0 "terminate a server process" )
+insert ( 2172 1255 0 "prepare for taking an online backup" )
+insert ( 2173 1255 0 "finish taking an online backup" )
+insert ( 2739 1255 0 "finish taking an online backup" )
+insert ( 3813 1255 0 "true if server is in online backup" )
+insert ( 3814 1255 0 "start time of an online backup" )
+insert ( 3436 1255 0 "promote standby server" )
+insert ( 2848 1255 0 "switch to new wal file" )
+insert ( 3098 1255 0 "create a named restore point" )
+insert ( 2849 1255 0 "current wal write location" )
+insert ( 2852 1255 0 "current wal insert location" )
+insert ( 3330 1255 0 "current wal flush location" )
+insert ( 2850 1255 0 "wal filename and byte offset, given a wal location" )
+insert ( 2851 1255 0 "wal filename, given a wal location" )
+insert ( 3165 1255 0 "difference in bytes, given two wal locations" )
+insert ( 3809 1255 0 "export a snapshot" )
+insert ( 3810 1255 0 "true if server is in recovery" )
+insert ( 3820 1255 0 "current wal flush location" )
+insert ( 3821 1255 0 "last wal replay location" )
+insert ( 3830 1255 0 "timestamp of last replay xact" )
+insert ( 3071 1255 0 "pause wal replay" )
+insert ( 3072 1255 0 "resume wal replay, if it was paused" )
+insert ( 3073 1255 0 "true if wal replay is paused" )
+insert ( 2621 1255 0 "reload configuration files" )
+insert ( 2622 1255 0 "rotate log file" )
+insert ( 4099 1255 0 "rotate log file - old version for adminpack 1.0" )
+insert ( 3800 1255 0 "current logging collector file location" )
+insert ( 3801 1255 0 "current logging collector file location" )
+insert ( 2623 1255 0 "get information about file" )
+insert ( 3307 1255 0 "get information about file" )
+insert ( 2624 1255 0 "read text from a file" )
+insert ( 3293 1255 0 "read text from a file" )
+insert ( 4100 1255 0 "read text from a file - old version for adminpack 1.0" )
+insert ( 3826 1255 0 "read text from a file" )
+insert ( 3827 1255 0 "read bytea from a file" )
+insert ( 3295 1255 0 "read bytea from a file" )
+insert ( 3828 1255 0 "read bytea from a file" )
+insert ( 2625 1255 0 "list all files in a directory" )
+insert ( 3297 1255 0 "list all files in a directory" )
+insert ( 2626 1255 0 "sleep for the specified time in seconds" )
+insert ( 3935 1255 0 "sleep for the specified interval" )
+insert ( 3936 1255 0 "sleep until the specified time" )
+insert ( 315 1255 0 "Is JIT compilation available in this session?" )
+insert ( 2971 1255 0 "convert boolean to text" )
+insert ( 2100 1255 0 "the average (arithmetic mean) as numeric of all bigint values" )
+insert ( 2101 1255 0 "the average (arithmetic mean) as numeric of all integer values" )
+insert ( 2102 1255 0 "the average (arithmetic mean) as numeric of all smallint values" )
+insert ( 2103 1255 0 "the average (arithmetic mean) as numeric of all numeric values" )
+insert ( 2104 1255 0 "the average (arithmetic mean) as float8 of all float4 values" )
+insert ( 2105 1255 0 "the average (arithmetic mean) as float8 of all float8 values" )
+insert ( 2106 1255 0 "the average (arithmetic mean) as interval of all interval values" )
+insert ( 2107 1255 0 "sum as numeric across all bigint input values" )
+insert ( 2108 1255 0 "sum as bigint across all integer input values" )
+insert ( 2109 1255 0 "sum as bigint across all smallint input values" )
+insert ( 2110 1255 0 "sum as float4 across all float4 input values" )
+insert ( 2111 1255 0 "sum as float8 across all float8 input values" )
+insert ( 2112 1255 0 "sum as money across all money input values" )
+insert ( 2113 1255 0 "sum as interval across all interval input values" )
+insert ( 2114 1255 0 "sum as numeric across all numeric input values" )
+insert ( 2115 1255 0 "maximum value of all bigint input values" )
+insert ( 2116 1255 0 "maximum value of all integer input values" )
+insert ( 2117 1255 0 "maximum value of all smallint input values" )
+insert ( 2118 1255 0 "maximum value of all oid input values" )
+insert ( 2119 1255 0 "maximum value of all float4 input values" )
+insert ( 2120 1255 0 "maximum value of all float8 input values" )
+insert ( 2122 1255 0 "maximum value of all date input values" )
+insert ( 2123 1255 0 "maximum value of all time input values" )
+insert ( 2124 1255 0 "maximum value of all time with time zone input values" )
+insert ( 2125 1255 0 "maximum value of all money input values" )
+insert ( 2126 1255 0 "maximum value of all timestamp input values" )
+insert ( 2127 1255 0 "maximum value of all timestamp with time zone input values" )
+insert ( 2128 1255 0 "maximum value of all interval input values" )
+insert ( 2129 1255 0 "maximum value of all text input values" )
+insert ( 2130 1255 0 "maximum value of all numeric input values" )
+insert ( 2050 1255 0 "maximum value of all anyarray input values" )
+insert ( 2244 1255 0 "maximum value of all bpchar input values" )
+insert ( 2797 1255 0 "maximum value of all tid input values" )
+insert ( 3564 1255 0 "maximum value of all inet input values" )
+insert ( 4189 1255 0 "maximum value of all pg_lsn input values" )
+insert ( 2131 1255 0 "minimum value of all bigint input values" )
+insert ( 2132 1255 0 "minimum value of all integer input values" )
+insert ( 2133 1255 0 "minimum value of all smallint input values" )
+insert ( 2134 1255 0 "minimum value of all oid input values" )
+insert ( 2135 1255 0 "minimum value of all float4 input values" )
+insert ( 2136 1255 0 "minimum value of all float8 input values" )
+insert ( 2138 1255 0 "minimum value of all date input values" )
+insert ( 2139 1255 0 "minimum value of all time input values" )
+insert ( 2140 1255 0 "minimum value of all time with time zone input values" )
+insert ( 2141 1255 0 "minimum value of all money input values" )
+insert ( 2142 1255 0 "minimum value of all timestamp input values" )
+insert ( 2143 1255 0 "minimum value of all timestamp with time zone input values" )
+insert ( 2144 1255 0 "minimum value of all interval input values" )
+insert ( 2145 1255 0 "minimum value of all text values" )
+insert ( 2146 1255 0 "minimum value of all numeric input values" )
+insert ( 2051 1255 0 "minimum value of all anyarray input values" )
+insert ( 2245 1255 0 "minimum value of all bpchar input values" )
+insert ( 2798 1255 0 "minimum value of all tid input values" )
+insert ( 3565 1255 0 "minimum value of all inet input values" )
+insert ( 4190 1255 0 "minimum value of all pg_lsn input values" )
+insert ( 2147 1255 0 "number of input rows for which the input expression is not null" )
+insert ( 2803 1255 0 "number of input rows" )
+insert ( 2718 1255 0 "population variance of bigint input values (square of the population standard deviation)" )
+insert ( 2719 1255 0 "population variance of integer input values (square of the population standard deviation)" )
+insert ( 2720 1255 0 "population variance of smallint input values (square of the population standard deviation)" )
+insert ( 2721 1255 0 "population variance of float4 input values (square of the population standard deviation)" )
+insert ( 2722 1255 0 "population variance of float8 input values (square of the population standard deviation)" )
+insert ( 2723 1255 0 "population variance of numeric input values (square of the population standard deviation)" )
+insert ( 2641 1255 0 "sample variance of bigint input values (square of the sample standard deviation)" )
+insert ( 2642 1255 0 "sample variance of integer input values (square of the sample standard deviation)" )
+insert ( 2643 1255 0 "sample variance of smallint input values (square of the sample standard deviation)" )
+insert ( 2644 1255 0 "sample variance of float4 input values (square of the sample standard deviation)" )
+insert ( 2645 1255 0 "sample variance of float8 input values (square of the sample standard deviation)" )
+insert ( 2646 1255 0 "sample variance of numeric input values (square of the sample standard deviation)" )
+insert ( 2148 1255 0 "historical alias for var_samp" )
+insert ( 2149 1255 0 "historical alias for var_samp" )
+insert ( 2150 1255 0 "historical alias for var_samp" )
+insert ( 2151 1255 0 "historical alias for var_samp" )
+insert ( 2152 1255 0 "historical alias for var_samp" )
+insert ( 2153 1255 0 "historical alias for var_samp" )
+insert ( 2724 1255 0 "population standard deviation of bigint input values" )
+insert ( 2725 1255 0 "population standard deviation of integer input values" )
+insert ( 2726 1255 0 "population standard deviation of smallint input values" )
+insert ( 2727 1255 0 "population standard deviation of float4 input values" )
+insert ( 2728 1255 0 "population standard deviation of float8 input values" )
+insert ( 2729 1255 0 "population standard deviation of numeric input values" )
+insert ( 2712 1255 0 "sample standard deviation of bigint input values" )
+insert ( 2713 1255 0 "sample standard deviation of integer input values" )
+insert ( 2714 1255 0 "sample standard deviation of smallint input values" )
+insert ( 2715 1255 0 "sample standard deviation of float4 input values" )
+insert ( 2716 1255 0 "sample standard deviation of float8 input values" )
+insert ( 2717 1255 0 "sample standard deviation of numeric input values" )
+insert ( 2154 1255 0 "historical alias for stddev_samp" )
+insert ( 2155 1255 0 "historical alias for stddev_samp" )
+insert ( 2156 1255 0 "historical alias for stddev_samp" )
+insert ( 2157 1255 0 "historical alias for stddev_samp" )
+insert ( 2158 1255 0 "historical alias for stddev_samp" )
+insert ( 2159 1255 0 "historical alias for stddev_samp" )
+insert ( 2818 1255 0 "number of input rows in which both expressions are not null" )
+insert ( 2819 1255 0 "sum of squares of the independent variable (sum(X^2) - sum(X)^2/N)" )
+insert ( 2820 1255 0 "sum of squares of the dependent variable (sum(Y^2) - sum(Y)^2/N)" )
+insert ( 2821 1255 0 "sum of products of independent times dependent variable (sum(X*Y) - sum(X) * sum(Y)/N)" )
+insert ( 2822 1255 0 "average of the independent variable (sum(X)/N)" )
+insert ( 2823 1255 0 "average of the dependent variable (sum(Y)/N)" )
+insert ( 2824 1255 0 "square of the correlation coefficient" )
+insert ( 2825 1255 0 "slope of the least-squares-fit linear equation determined by the (X, Y) pairs" )
+insert ( 2826 1255 0 "y-intercept of the least-squares-fit linear equation determined by the (X, Y) pairs" )
+insert ( 2827 1255 0 "population covariance" )
+insert ( 2828 1255 0 "sample covariance" )
+insert ( 2829 1255 0 "correlation coefficient" )
+insert ( 2166 1255 0 less-equal-greater )
+insert ( 3332 1255 0 "sort support" )
+insert ( 2180 1255 0 less-equal-greater )
+insert ( 3333 1255 0 "sort support" )
+insert ( 2188 1255 0 less-equal-greater )
+insert ( 2189 1255 0 less-equal-greater )
+insert ( 2190 1255 0 less-equal-greater )
+insert ( 2191 1255 0 less-equal-greater )
+insert ( 2192 1255 0 less-equal-greater )
+insert ( 2193 1255 0 less-equal-greater )
+insert ( 2194 1255 0 less-equal-greater )
+insert ( 2195 1255 0 less-equal-greater )
+insert ( 2212 1255 0 "I/O" )
+insert ( 2213 1255 0 "I/O" )
+insert ( 2214 1255 0 "I/O" )
+insert ( 2215 1255 0 "I/O" )
+insert ( 3492 1255 0 "convert operator name to regoper" )
+insert ( 3476 1255 0 "convert operator name to regoperator" )
+insert ( 2216 1255 0 "I/O" )
+insert ( 2217 1255 0 "I/O" )
+insert ( 2218 1255 0 "I/O" )
+insert ( 2219 1255 0 "I/O" )
+insert ( 3495 1255 0 "convert classname to regclass" )
+insert ( 4193 1255 0 "I/O" )
+insert ( 4194 1255 0 "I/O" )
+insert ( 4195 1255 0 "convert classname to regcollation" )
+insert ( 2220 1255 0 "I/O" )
+insert ( 2221 1255 0 "I/O" )
+insert ( 3493 1255 0 "convert type name to regtype" )
+insert ( 1079 1255 0 "convert text to regclass" )
+insert ( 4098 1255 0 "I/O" )
+insert ( 4092 1255 0 "I/O" )
+insert ( 4093 1255 0 "convert role name to regrole" )
+insert ( 4084 1255 0 "I/O" )
+insert ( 4085 1255 0 "I/O" )
+insert ( 4086 1255 0 "convert namespace name to regnamespace" )
+insert ( 1268 1255 0 "parse qualified identifier to array of identifiers" )
+insert ( 2246 1255 0 "(internal)" )
+insert ( 2247 1255 0 "(internal)" )
+insert ( 2248 1255 0 "(internal)" )
+insert ( 2250 1255 0 "user privilege on database by username, database name" )
+insert ( 2251 1255 0 "user privilege on database by username, database oid" )
+insert ( 2252 1255 0 "user privilege on database by user oid, database name" )
+insert ( 2253 1255 0 "user privilege on database by user oid, database oid" )
+insert ( 2254 1255 0 "current user privilege on database by database name" )
+insert ( 2255 1255 0 "current user privilege on database by database oid" )
+insert ( 2256 1255 0 "user privilege on function by username, function name" )
+insert ( 2257 1255 0 "user privilege on function by username, function oid" )
+insert ( 2258 1255 0 "user privilege on function by user oid, function name" )
+insert ( 2259 1255 0 "user privilege on function by user oid, function oid" )
+insert ( 2260 1255 0 "current user privilege on function by function name" )
+insert ( 2261 1255 0 "current user privilege on function by function oid" )
+insert ( 2262 1255 0 "user privilege on language by username, language name" )
+insert ( 2263 1255 0 "user privilege on language by username, language oid" )
+insert ( 2264 1255 0 "user privilege on language by user oid, language name" )
+insert ( 2265 1255 0 "user privilege on language by user oid, language oid" )
+insert ( 2266 1255 0 "current user privilege on language by language name" )
+insert ( 2267 1255 0 "current user privilege on language by language oid" )
+insert ( 2268 1255 0 "user privilege on schema by username, schema name" )
+insert ( 2269 1255 0 "user privilege on schema by username, schema oid" )
+insert ( 2270 1255 0 "user privilege on schema by user oid, schema name" )
+insert ( 2271 1255 0 "user privilege on schema by user oid, schema oid" )
+insert ( 2272 1255 0 "current user privilege on schema by schema name" )
+insert ( 2273 1255 0 "current user privilege on schema by schema oid" )
+insert ( 2390 1255 0 "user privilege on tablespace by username, tablespace name" )
+insert ( 2391 1255 0 "user privilege on tablespace by username, tablespace oid" )
+insert ( 2392 1255 0 "user privilege on tablespace by user oid, tablespace name" )
+insert ( 2393 1255 0 "user privilege on tablespace by user oid, tablespace oid" )
+insert ( 2394 1255 0 "current user privilege on tablespace by tablespace name" )
+insert ( 2395 1255 0 "current user privilege on tablespace by tablespace oid" )
+insert ( 3000 1255 0 "user privilege on foreign data wrapper by username, foreign data wrapper name" )
+insert ( 3001 1255 0 "user privilege on foreign data wrapper by username, foreign data wrapper oid" )
+insert ( 3002 1255 0 "user privilege on foreign data wrapper by user oid, foreign data wrapper name" )
+insert ( 3003 1255 0 "user privilege on foreign data wrapper by user oid, foreign data wrapper oid" )
+insert ( 3004 1255 0 "current user privilege on foreign data wrapper by foreign data wrapper name" )
+insert ( 3005 1255 0 "current user privilege on foreign data wrapper by foreign data wrapper oid" )
+insert ( 3006 1255 0 "user privilege on server by username, server name" )
+insert ( 3007 1255 0 "user privilege on server by username, server oid" )
+insert ( 3008 1255 0 "user privilege on server by user oid, server name" )
+insert ( 3009 1255 0 "user privilege on server by user oid, server oid" )
+insert ( 3010 1255 0 "current user privilege on server by server name" )
+insert ( 3011 1255 0 "current user privilege on server by server oid" )
+insert ( 3138 1255 0 "user privilege on type by username, type name" )
+insert ( 3139 1255 0 "user privilege on type by username, type oid" )
+insert ( 3140 1255 0 "user privilege on type by user oid, type name" )
+insert ( 3141 1255 0 "user privilege on type by user oid, type oid" )
+insert ( 3142 1255 0 "current user privilege on type by type name" )
+insert ( 3143 1255 0 "current user privilege on type by type oid" )
+insert ( 2705 1255 0 "user privilege on role by username, role name" )
+insert ( 2706 1255 0 "user privilege on role by username, role oid" )
+insert ( 2707 1255 0 "user privilege on role by user oid, role name" )
+insert ( 2708 1255 0 "user privilege on role by user oid, role oid" )
+insert ( 2709 1255 0 "current user privilege on role by role name" )
+insert ( 2710 1255 0 "current user privilege on role by role oid" )
+insert ( 1269 1255 0 "bytes required to store the value, perhaps with compression" )
+insert ( 2322 1255 0 "total disk space usage for the specified tablespace" )
+insert ( 2323 1255 0 "total disk space usage for the specified tablespace" )
+insert ( 2324 1255 0 "total disk space usage for the specified database" )
+insert ( 2168 1255 0 "total disk space usage for the specified database" )
+insert ( 2325 1255 0 "disk space usage for the main fork of the specified table or index" )
+insert ( 2332 1255 0 "disk space usage for the specified fork of a table or index" )
+insert ( 2286 1255 0 "total disk space usage for the specified table and associated indexes" )
+insert ( 2288 1255 0 "convert a long int to a human readable text using size units" )
+insert ( 3166 1255 0 "convert a numeric to a human readable text using size units" )
+insert ( 3334 1255 0 "convert a size in human-readable format with size units into bytes" )
+insert ( 2997 1255 0 "disk space usage for the specified table, including TOAST, free space and visibility map" )
+insert ( 2998 1255 0 "disk space usage for all indexes attached to the specified table" )
+insert ( 2999 1255 0 "filenode identifier of relation" )
+insert ( 3454 1255 0 "relation OID for filenode and tablespace" )
+insert ( 3034 1255 0 "file path of relation" )
+insert ( 2316 1255 0 "(internal)" )
+insert ( 2290 1255 0 "I/O" )
+insert ( 2291 1255 0 "I/O" )
+insert ( 2292 1255 0 "I/O" )
+insert ( 2293 1255 0 "I/O" )
+insert ( 2294 1255 0 "I/O" )
+insert ( 2295 1255 0 "I/O" )
+insert ( 2296 1255 0 "I/O" )
+insert ( 2297 1255 0 "I/O" )
+insert ( 2298 1255 0 "I/O" )
+insert ( 2299 1255 0 "I/O" )
+insert ( 2300 1255 0 "I/O" )
+insert ( 2301 1255 0 "I/O" )
+insert ( 3594 1255 0 "I/O" )
+insert ( 3595 1255 0 "I/O" )
+insert ( 2302 1255 0 "I/O" )
+insert ( 2303 1255 0 "I/O" )
+insert ( 2304 1255 0 "I/O" )
+insert ( 2305 1255 0 "I/O" )
+insert ( 2312 1255 0 "I/O" )
+insert ( 2313 1255 0 "I/O" )
+insert ( 2398 1255 0 "I/O" )
+insert ( 2399 1255 0 "I/O" )
+insert ( 2597 1255 0 "I/O" )
+insert ( 2598 1255 0 "I/O" )
+insert ( 2777 1255 0 "I/O" )
+insert ( 2778 1255 0 "I/O" )
+insert ( 3116 1255 0 "I/O" )
+insert ( 3117 1255 0 "I/O" )
+insert ( 326 1255 0 "I/O" )
+insert ( 327 1255 0 "I/O" )
+insert ( 3311 1255 0 "I/O" )
+insert ( 3312 1255 0 "I/O" )
+insert ( 267 1255 0 "I/O" )
+insert ( 268 1255 0 "I/O" )
+insert ( 5086 1255 0 "I/O" )
+insert ( 5087 1255 0 "I/O" )
+insert ( 5088 1255 0 "I/O" )
+insert ( 5089 1255 0 "I/O" )
+insert ( 5090 1255 0 "I/O" )
+insert ( 5091 1255 0 "I/O" )
+insert ( 5092 1255 0 "I/O" )
+insert ( 5093 1255 0 "I/O" )
+insert ( 5094 1255 0 "I/O" )
+insert ( 5095 1255 0 "I/O" )
+insert ( 3313 1255 0 "BERNOULLI tablesample method handler" )
+insert ( 3314 1255 0 "SYSTEM tablesample method handler" )
+insert ( 2311 1255 0 "MD5 hash" )
+insert ( 2321 1255 0 "MD5 hash" )
+insert ( 3419 1255 0 "SHA-224 hash" )
+insert ( 3420 1255 0 "SHA-256 hash" )
+insert ( 3421 1255 0 "SHA-384 hash" )
+insert ( 3422 1255 0 "SHA-512 hash" )
+insert ( 2344 1255 0 less-equal-greater )
+insert ( 2357 1255 0 less-equal-greater )
+insert ( 2370 1255 0 less-equal-greater )
+insert ( 2383 1255 0 less-equal-greater )
+insert ( 2526 1255 0 less-equal-greater )
+insert ( 2533 1255 0 less-equal-greater )
+insert ( 2400 1255 0 "I/O" )
+insert ( 2401 1255 0 "I/O" )
+insert ( 2402 1255 0 "I/O" )
+insert ( 2403 1255 0 "I/O" )
+insert ( 2404 1255 0 "I/O" )
+insert ( 2405 1255 0 "I/O" )
+insert ( 2406 1255 0 "I/O" )
+insert ( 2407 1255 0 "I/O" )
+insert ( 2408 1255 0 "I/O" )
+insert ( 2409 1255 0 "I/O" )
+insert ( 2410 1255 0 "I/O" )
+insert ( 2411 1255 0 "I/O" )
+insert ( 2412 1255 0 "I/O" )
+insert ( 2413 1255 0 "I/O" )
+insert ( 2414 1255 0 "I/O" )
+insert ( 2415 1255 0 "I/O" )
+insert ( 2416 1255 0 "I/O" )
+insert ( 2417 1255 0 "I/O" )
+insert ( 2418 1255 0 "I/O" )
+insert ( 2419 1255 0 "I/O" )
+insert ( 2420 1255 0 "I/O" )
+insert ( 2421 1255 0 "I/O" )
+insert ( 2422 1255 0 "I/O" )
+insert ( 2423 1255 0 "I/O" )
+insert ( 2424 1255 0 "I/O" )
+insert ( 2425 1255 0 "I/O" )
+insert ( 2426 1255 0 "I/O" )
+insert ( 2427 1255 0 "I/O" )
+insert ( 2428 1255 0 "I/O" )
+insert ( 2429 1255 0 "I/O" )
+insert ( 2430 1255 0 "I/O" )
+insert ( 2431 1255 0 "I/O" )
+insert ( 2432 1255 0 "I/O" )
+insert ( 2433 1255 0 "I/O" )
+insert ( 2434 1255 0 "I/O" )
+insert ( 2435 1255 0 "I/O" )
+insert ( 2436 1255 0 "I/O" )
+insert ( 2437 1255 0 "I/O" )
+insert ( 2438 1255 0 "I/O" )
+insert ( 2439 1255 0 "I/O" )
+insert ( 2440 1255 0 "I/O" )
+insert ( 2441 1255 0 "I/O" )
+insert ( 2442 1255 0 "I/O" )
+insert ( 2443 1255 0 "I/O" )
+insert ( 2444 1255 0 "I/O" )
+insert ( 2445 1255 0 "I/O" )
+insert ( 2446 1255 0 "I/O" )
+insert ( 2447 1255 0 "I/O" )
+insert ( 2448 1255 0 "I/O" )
+insert ( 2449 1255 0 "I/O" )
+insert ( 2450 1255 0 "I/O" )
+insert ( 2451 1255 0 "I/O" )
+insert ( 2452 1255 0 "I/O" )
+insert ( 2453 1255 0 "I/O" )
+insert ( 4196 1255 0 "I/O" )
+insert ( 4197 1255 0 "I/O" )
+insert ( 2454 1255 0 "I/O" )
+insert ( 2455 1255 0 "I/O" )
+insert ( 4094 1255 0 "I/O" )
+insert ( 4095 1255 0 "I/O" )
+insert ( 4087 1255 0 "I/O" )
+insert ( 4088 1255 0 "I/O" )
+insert ( 2456 1255 0 "I/O" )
+insert ( 2457 1255 0 "I/O" )
+insert ( 2458 1255 0 "I/O" )
+insert ( 2459 1255 0 "I/O" )
+insert ( 2460 1255 0 "I/O" )
+insert ( 2461 1255 0 "I/O" )
+insert ( 2468 1255 0 "I/O" )
+insert ( 2469 1255 0 "I/O" )
+insert ( 2470 1255 0 "I/O" )
+insert ( 2471 1255 0 "I/O" )
+insert ( 2472 1255 0 "I/O" )
+insert ( 2473 1255 0 "I/O" )
+insert ( 2474 1255 0 "I/O" )
+insert ( 2475 1255 0 "I/O" )
+insert ( 2476 1255 0 "I/O" )
+insert ( 2477 1255 0 "I/O" )
+insert ( 2478 1255 0 "I/O" )
+insert ( 2479 1255 0 "I/O" )
+insert ( 2480 1255 0 "I/O" )
+insert ( 2481 1255 0 "I/O" )
+insert ( 2482 1255 0 "I/O" )
+insert ( 2483 1255 0 "I/O" )
+insert ( 2484 1255 0 "I/O" )
+insert ( 2485 1255 0 "I/O" )
+insert ( 2486 1255 0 "I/O" )
+insert ( 2487 1255 0 "I/O" )
+insert ( 2488 1255 0 "I/O" )
+insert ( 2489 1255 0 "I/O" )
+insert ( 2490 1255 0 "I/O" )
+insert ( 2491 1255 0 "I/O" )
+insert ( 2492 1255 0 "I/O" )
+insert ( 2493 1255 0 "I/O" )
+insert ( 2494 1255 0 "I/O" )
+insert ( 2495 1255 0 "I/O" )
+insert ( 2496 1255 0 "I/O" )
+insert ( 2497 1255 0 "I/O" )
+insert ( 2498 1255 0 "I/O" )
+insert ( 2499 1255 0 "I/O" )
+insert ( 2500 1255 0 "I/O" )
+insert ( 2501 1255 0 "I/O" )
+insert ( 2502 1255 0 "I/O" )
+insert ( 2503 1255 0 "I/O" )
+insert ( 3120 1255 0 "I/O" )
+insert ( 3121 1255 0 "I/O" )
+insert ( 3446 1255 0 "I/O" )
+insert ( 3447 1255 0 "I/O" )
+insert ( 2504 1255 0 "source text of a rule with pretty-print option" )
+insert ( 2505 1255 0 "select statement of a view with pretty-print option" )
+insert ( 2506 1255 0 "select statement of a view with pretty-print option" )
+insert ( 3159 1255 0 "select statement of a view with pretty-printing and specified line wrapping" )
+insert ( 2507 1255 0 "index description (full create statement or single expression) with pretty-print option" )
+insert ( 2508 1255 0 "constraint description with pretty-print option" )
+insert ( 2509 1255 0 "deparse an encoded expression with pretty-print option" )
+insert ( 2510 1255 0 "get the prepared statements for this session" )
+insert ( 2511 1255 0 "get the open cursors for this session" )
+insert ( 2599 1255 0 "get the available time zone abbreviations" )
+insert ( 2856 1255 0 "get the available time zone names" )
+insert ( 2730 1255 0 "trigger description with pretty-print option" )
+insert ( 3035 1255 0 "get the channels that the current backend listens to" )
+insert ( 3036 1255 0 "send a notification event" )
+insert ( 3296 1255 0 "get the fraction of the asynchronous notification queue currently in use" )
+insert ( 5052 1255 0 "allocations from the main shared memory segment" )
+insert ( 1066 1255 0 "non-persistent series generator" )
+insert ( 1067 1255 0 "non-persistent series generator" )
+insert ( 3994 1255 0 "planner support for generate_series" )
+insert ( 1068 1255 0 "non-persistent series generator" )
+insert ( 1069 1255 0 "non-persistent series generator" )
+insert ( 3995 1255 0 "planner support for generate_series" )
+insert ( 3259 1255 0 "non-persistent series generator" )
+insert ( 3260 1255 0 "non-persistent series generator" )
+insert ( 938 1255 0 "non-persistent series generator" )
+insert ( 939 1255 0 "non-persistent series generator" )
+insert ( 2515 1255 0 "aggregate transition function" )
+insert ( 2516 1255 0 "aggregate transition function" )
+insert ( 3496 1255 0 "aggregate transition function" )
+insert ( 3497 1255 0 "aggregate transition function" )
+insert ( 3498 1255 0 "aggregate final function" )
+insert ( 3499 1255 0 "aggregate final function" )
+insert ( 2517 1255 0 "boolean-and aggregate" )
+insert ( 2518 1255 0 "boolean-or aggregate" )
+insert ( 2519 1255 0 "boolean-and aggregate" )
+insert ( 2236 1255 0 "bitwise-and smallint aggregate" )
+insert ( 2237 1255 0 "bitwise-or smallint aggregate" )
+insert ( 2238 1255 0 "bitwise-and integer aggregate" )
+insert ( 2239 1255 0 "bitwise-or integer aggregate" )
+insert ( 2240 1255 0 "bitwise-and bigint aggregate" )
+insert ( 2241 1255 0 "bitwise-or bigint aggregate" )
+insert ( 2242 1255 0 "bitwise-and bit aggregate" )
+insert ( 2243 1255 0 "bitwise-or bit aggregate" )
+insert ( 2556 1255 0 "get OIDs of databases in a tablespace" )
+insert ( 2557 1255 0 "convert int4 to boolean" )
+insert ( 2558 1255 0 "convert boolean to int4" )
+insert ( 2559 1255 0 "current value from last used sequence" )
+insert ( 2560 1255 0 "postmaster start time" )
+insert ( 2034 1255 0 "configuration load time" )
+insert ( 2578 1255 0 "GiST support" )
+insert ( 2581 1255 0 "GiST support" )
+insert ( 2582 1255 0 "GiST support" )
+insert ( 2583 1255 0 "GiST support" )
+insert ( 2584 1255 0 "GiST support" )
+insert ( 3998 1255 0 "GiST support" )
+insert ( 2585 1255 0 "GiST support" )
+insert ( 2586 1255 0 "GiST support" )
+insert ( 2591 1255 0 "GiST support" )
+insert ( 2592 1255 0 "GiST support" )
+insert ( 1030 1255 0 "GiST support" )
+insert ( 3282 1255 0 "GiST support" )
+insert ( 2179 1255 0 "GiST support" )
+insert ( 3064 1255 0 "GiST support" )
+insert ( 3280 1255 0 "GiST support" )
+insert ( 3288 1255 0 "GiST support" )
+insert ( 2743 1255 0 "GIN array support" )
+insert ( 2774 1255 0 "GIN array support" )
+insert ( 2744 1255 0 "GIN array support" )
+insert ( 3920 1255 0 "GIN array support" )
+insert ( 3076 1255 0 "GIN array support (obsolete)" )
+insert ( 3383 1255 0 "BRIN minmax support" )
+insert ( 3384 1255 0 "BRIN minmax support" )
+insert ( 3385 1255 0 "BRIN minmax support" )
+insert ( 3386 1255 0 "BRIN minmax support" )
+insert ( 4105 1255 0 "BRIN inclusion support" )
+insert ( 4106 1255 0 "BRIN inclusion support" )
+insert ( 4107 1255 0 "BRIN inclusion support" )
+insert ( 4108 1255 0 "BRIN inclusion support" )
+insert ( 2880 1255 0 "obtain exclusive advisory lock" )
+insert ( 3089 1255 0 "obtain exclusive advisory lock" )
+insert ( 2881 1255 0 "obtain shared advisory lock" )
+insert ( 3090 1255 0 "obtain shared advisory lock" )
+insert ( 2882 1255 0 "obtain exclusive advisory lock if available" )
+insert ( 3091 1255 0 "obtain exclusive advisory lock if available" )
+insert ( 2883 1255 0 "obtain shared advisory lock if available" )
+insert ( 3092 1255 0 "obtain shared advisory lock if available" )
+insert ( 2884 1255 0 "release exclusive advisory lock" )
+insert ( 2885 1255 0 "release shared advisory lock" )
+insert ( 2886 1255 0 "obtain exclusive advisory lock" )
+insert ( 3093 1255 0 "obtain exclusive advisory lock" )
+insert ( 2887 1255 0 "obtain shared advisory lock" )
+insert ( 3094 1255 0 "obtain shared advisory lock" )
+insert ( 2888 1255 0 "obtain exclusive advisory lock if available" )
+insert ( 3095 1255 0 "obtain exclusive advisory lock if available" )
+insert ( 2889 1255 0 "obtain shared advisory lock if available" )
+insert ( 3096 1255 0 "obtain shared advisory lock if available" )
+insert ( 2890 1255 0 "release exclusive advisory lock" )
+insert ( 2891 1255 0 "release shared advisory lock" )
+insert ( 2892 1255 0 "release all advisory locks" )
+insert ( 2893 1255 0 "I/O" )
+insert ( 2894 1255 0 "I/O" )
+insert ( 2895 1255 0 "generate XML comment" )
+insert ( 2896 1255 0 "perform a non-validating parse of a character string to produce an XML value" )
+insert ( 2897 1255 0 "validate an XML value" )
+insert ( 2898 1255 0 "I/O" )
+insert ( 2899 1255 0 "I/O" )
+insert ( 2900 1255 0 "aggregate transition function" )
+insert ( 2901 1255 0 "concatenate XML values" )
+insert ( 2922 1255 0 "serialize an XML value to a character string" )
+insert ( 2923 1255 0 "map table contents to XML" )
+insert ( 2924 1255 0 "map query result to XML" )
+insert ( 2925 1255 0 "map rows from cursor to XML" )
+insert ( 2926 1255 0 "map table structure to XML Schema" )
+insert ( 2927 1255 0 "map query result structure to XML Schema" )
+insert ( 2928 1255 0 "map cursor structure to XML Schema" )
+insert ( 2929 1255 0 "map table contents and structure to XML and XML Schema" )
+insert ( 2930 1255 0 "map query result and structure to XML and XML Schema" )
+insert ( 2933 1255 0 "map schema contents to XML" )
+insert ( 2934 1255 0 "map schema structure to XML Schema" )
+insert ( 2935 1255 0 "map schema contents and structure to XML and XML Schema" )
+insert ( 2936 1255 0 "map database contents to XML" )
+insert ( 2937 1255 0 "map database structure to XML Schema" )
+insert ( 2938 1255 0 "map database contents and structure to XML and XML Schema" )
+insert ( 2931 1255 0 "evaluate XPath expression, with namespaces support" )
+insert ( 2932 1255 0 "evaluate XPath expression" )
+insert ( 2614 1255 0 "test XML value against XPath expression" )
+insert ( 3049 1255 0 "test XML value against XPath expression, with namespace support" )
+insert ( 3050 1255 0 "test XML value against XPath expression" )
+insert ( 3051 1255 0 "determine if a string is well formed XML" )
+insert ( 3052 1255 0 "determine if a string is well formed XML document" )
+insert ( 3053 1255 0 "determine if a string is well formed XML content" )
+insert ( 321 1255 0 "I/O" )
+insert ( 322 1255 0 "I/O" )
+insert ( 323 1255 0 "I/O" )
+insert ( 324 1255 0 "I/O" )
+insert ( 3153 1255 0 "map array to json" )
+insert ( 3154 1255 0 "map array to json with optional pretty printing" )
+insert ( 3155 1255 0 "map row to json" )
+insert ( 3156 1255 0 "map row to json with optional pretty printing" )
+insert ( 3173 1255 0 "json aggregate transition function" )
+insert ( 3174 1255 0 "json aggregate final function" )
+insert ( 3175 1255 0 "aggregate input into json" )
+insert ( 3180 1255 0 "json object aggregate transition function" )
+insert ( 3196 1255 0 "json object aggregate final function" )
+insert ( 3197 1255 0 "aggregate input into a json object" )
+insert ( 3198 1255 0 "build a json array from any inputs" )
+insert ( 3199 1255 0 "build an empty json array" )
+insert ( 3200 1255 0 "build a json object from pairwise key/value inputs" )
+insert ( 3201 1255 0 "build an empty json object" )
+insert ( 3202 1255 0 "map text array of key value pairs to json object" )
+insert ( 3203 1255 0 "map text arrays of keys and values to json object" )
+insert ( 3176 1255 0 "map input to json" )
+insert ( 3261 1255 0 "remove object fields with null values from json" )
+insert ( 3951 1255 0 "get value from json with path elements" )
+insert ( 3953 1255 0 "get value from json as text with path elements" )
+insert ( 3955 1255 0 "key value pairs of a json object" )
+insert ( 3969 1255 0 "elements of json array" )
+insert ( 3956 1255 0 "length of json array" )
+insert ( 3957 1255 0 "get json object keys" )
+insert ( 3958 1255 0 "key value pairs of a json object" )
+insert ( 3959 1255 0 "key value pairs of a json object" )
+insert ( 3960 1255 0 "get record fields from a json object" )
+insert ( 3961 1255 0 "get set of records with fields from a json array of objects" )
+insert ( 3204 1255 0 "get record fields from a json object" )
+insert ( 3205 1255 0 "get set of records with fields from a json array of objects" )
+insert ( 3968 1255 0 "get the type of a json value" )
+insert ( 2952 1255 0 "I/O" )
+insert ( 2953 1255 0 "I/O" )
+insert ( 2960 1255 0 less-equal-greater )
+insert ( 3300 1255 0 "sort support" )
+insert ( 2961 1255 0 "I/O" )
+insert ( 2962 1255 0 "I/O" )
+insert ( 2963 1255 0 hash )
+insert ( 3412 1255 0 hash )
+insert ( 3432 1255 0 "generate random UUID" )
+insert ( 3229 1255 0 "I/O" )
+insert ( 3230 1255 0 "I/O" )
+insert ( 3238 1255 0 "I/O" )
+insert ( 3239 1255 0 "I/O" )
+insert ( 3251 1255 0 less-equal-greater )
+insert ( 3252 1255 0 hash )
+insert ( 3413 1255 0 hash )
+insert ( 4187 1255 0 "larger of two" )
+insert ( 4188 1255 0 "smaller of two" )
+insert ( 3504 1255 0 "I/O" )
+insert ( 3505 1255 0 "I/O" )
+insert ( 3506 1255 0 "I/O" )
+insert ( 3507 1255 0 "I/O" )
+insert ( 3514 1255 0 less-equal-greater )
+insert ( 3515 1255 0 hash )
+insert ( 3414 1255 0 hash )
+insert ( 3524 1255 0 "smaller of two" )
+insert ( 3525 1255 0 "larger of two" )
+insert ( 3526 1255 0 "maximum value of all enum input values" )
+insert ( 3527 1255 0 "minimum value of all enum input values" )
+insert ( 3528 1255 0 "first value of the input enum type" )
+insert ( 3529 1255 0 "last value of the input enum type" )
+insert ( 3530 1255 0 "range between the two given enum values, as an ordered array" )
+insert ( 3531 1255 0 "range of the given enum type, as an ordered array" )
+insert ( 3532 1255 0 "I/O" )
+insert ( 3533 1255 0 "I/O" )
+insert ( 3610 1255 0 "I/O" )
+insert ( 3639 1255 0 "I/O" )
+insert ( 3611 1255 0 "I/O" )
+insert ( 3638 1255 0 "I/O" )
+insert ( 3612 1255 0 "I/O" )
+insert ( 3641 1255 0 "I/O" )
+insert ( 3613 1255 0 "I/O" )
+insert ( 3640 1255 0 "I/O" )
+insert ( 3646 1255 0 "I/O" )
+insert ( 3647 1255 0 "I/O" )
+insert ( 3622 1255 0 less-equal-greater )
+insert ( 3711 1255 0 "number of lexemes" )
+insert ( 3623 1255 0 "strip position information" )
+insert ( 3624 1255 0 "set given weight for whole tsvector" )
+insert ( 3320 1255 0 "set given weight for given lexemes" )
+insert ( 3321 1255 0 "delete lexeme" )
+insert ( 3323 1255 0 "delete given lexemes" )
+insert ( 3322 1255 0 "expand tsvector to set of rows" )
+insert ( 3326 1255 0 "convert tsvector to array of lexemes" )
+insert ( 3327 1255 0 "build tsvector from array of lexemes" )
+insert ( 3319 1255 0 "delete lexemes that do not have one of the given weights" )
+insert ( 3648 1255 0 "GiST tsvector support" )
+insert ( 3649 1255 0 "GiST tsvector support" )
+insert ( 3650 1255 0 "GiST tsvector support" )
+insert ( 3651 1255 0 "GiST tsvector support" )
+insert ( 3652 1255 0 "GiST tsvector support" )
+insert ( 3653 1255 0 "GiST tsvector support" )
+insert ( 3654 1255 0 "GiST tsvector support" )
+insert ( 3790 1255 0 "GiST tsvector support (obsolete)" )
+insert ( 3434 1255 0 "GiST tsvector support" )
+insert ( 3656 1255 0 "GIN tsvector support" )
+insert ( 3657 1255 0 "GIN tsvector support" )
+insert ( 3658 1255 0 "GIN tsvector support" )
+insert ( 3921 1255 0 "GIN tsvector support" )
+insert ( 3724 1255 0 "GIN tsvector support" )
+insert ( 2700 1255 0 "GIN tsvector support" )
+insert ( 3077 1255 0 "GIN tsvector support (obsolete)" )
+insert ( 3087 1255 0 "GIN tsvector support (obsolete)" )
+insert ( 3088 1255 0 "GIN tsvector support (obsolete)" )
+insert ( 3791 1255 0 "GIN tsvector support (obsolete)" )
+insert ( 3792 1255 0 "GIN tsvector support (obsolete)" )
+insert ( 3789 1255 0 "clean up GIN pending list" )
+insert ( 3668 1255 0 less-equal-greater )
+insert ( 5004 1255 0 "phrase-concatenate with distance" )
+insert ( 3672 1255 0 "number of nodes" )
+insert ( 3673 1255 0 "show real useful query for GiST index" )
+insert ( 3684 1255 0 "rewrite tsquery" )
+insert ( 3685 1255 0 "rewrite tsquery" )
+insert ( 3695 1255 0 "GiST tsquery support" )
+insert ( 3697 1255 0 "GiST tsquery support" )
+insert ( 3698 1255 0 "GiST tsquery support" )
+insert ( 3699 1255 0 "GiST tsquery support" )
+insert ( 3700 1255 0 "GiST tsquery support" )
+insert ( 3701 1255 0 "GiST tsquery support" )
+insert ( 3793 1255 0 "GiST tsquery support (obsolete)" )
+insert ( 3686 1255 0 "restriction selectivity of tsvector @@ tsquery" )
+insert ( 3687 1255 0 "join selectivity of tsvector @@ tsquery" )
+insert ( 3688 1255 0 "tsvector typanalyze" )
+insert ( 3689 1255 0 "statistics of tsvector column" )
+insert ( 3690 1255 0 "statistics of tsvector column" )
+insert ( 3703 1255 0 relevance )
+insert ( 3704 1255 0 relevance )
+insert ( 3705 1255 0 relevance )
+insert ( 3706 1255 0 relevance )
+insert ( 3707 1255 0 relevance )
+insert ( 3708 1255 0 relevance )
+insert ( 3709 1255 0 relevance )
+insert ( 3710 1255 0 relevance )
+insert ( 3713 1255 0 "get parser''s token types" )
+insert ( 3714 1255 0 "get parser''s token types" )
+insert ( 3715 1255 0 "parse text to tokens" )
+insert ( 3716 1255 0 "parse text to tokens" )
+insert ( 3717 1255 0 "(internal)" )
+insert ( 3718 1255 0 "(internal)" )
+insert ( 3719 1255 0 "(internal)" )
+insert ( 3720 1255 0 "(internal)" )
+insert ( 3721 1255 0 "(internal)" )
+insert ( 3723 1255 0 "normalize one word by dictionary" )
+insert ( 3725 1255 0 "(internal)" )
+insert ( 3726 1255 0 "(internal)" )
+insert ( 3728 1255 0 "(internal)" )
+insert ( 3729 1255 0 "(internal)" )
+insert ( 3731 1255 0 "(internal)" )
+insert ( 3732 1255 0 "(internal)" )
+insert ( 3740 1255 0 "(internal)" )
+insert ( 3741 1255 0 "(internal)" )
+insert ( 3743 1255 0 "generate headline" )
+insert ( 3744 1255 0 "generate headline" )
+insert ( 3754 1255 0 "generate headline" )
+insert ( 3755 1255 0 "generate headline" )
+insert ( 4201 1255 0 "generate headline from jsonb" )
+insert ( 4202 1255 0 "generate headline from jsonb" )
+insert ( 4203 1255 0 "generate headline from jsonb" )
+insert ( 4204 1255 0 "generate headline from jsonb" )
+insert ( 4205 1255 0 "generate headline from json" )
+insert ( 4206 1255 0 "generate headline from json" )
+insert ( 4207 1255 0 "generate headline from json" )
+insert ( 4208 1255 0 "generate headline from json" )
+insert ( 3745 1255 0 "transform to tsvector" )
+insert ( 3746 1255 0 "make tsquery" )
+insert ( 3747 1255 0 "transform to tsquery" )
+insert ( 5006 1255 0 "transform to tsquery" )
+insert ( 5007 1255 0 "transform to tsquery" )
+insert ( 3749 1255 0 "transform to tsvector" )
+insert ( 3750 1255 0 "make tsquery" )
+insert ( 3751 1255 0 "transform to tsquery" )
+insert ( 5001 1255 0 "transform to tsquery" )
+insert ( 5009 1255 0 "transform to tsquery" )
+insert ( 4209 1255 0 "transform string values from jsonb to tsvector" )
+insert ( 4213 1255 0 "transform specified values from jsonb to tsvector" )
+insert ( 4210 1255 0 "transform string values from json to tsvector" )
+insert ( 4215 1255 0 "transform specified values from json to tsvector" )
+insert ( 4211 1255 0 "transform string values from jsonb to tsvector" )
+insert ( 4214 1255 0 "transform specified values from jsonb to tsvector" )
+insert ( 4212 1255 0 "transform string values from json to tsvector" )
+insert ( 4216 1255 0 "transform specified values from json to tsvector" )
+insert ( 3752 1255 0 "trigger for automatic update of tsvector column" )
+insert ( 3753 1255 0 "trigger for automatic update of tsvector column" )
+insert ( 3759 1255 0 "get current tsearch configuration" )
+insert ( 3736 1255 0 "I/O" )
+insert ( 3737 1255 0 "I/O" )
+insert ( 3738 1255 0 "I/O" )
+insert ( 3739 1255 0 "I/O" )
+insert ( 3771 1255 0 "I/O" )
+insert ( 3772 1255 0 "I/O" )
+insert ( 3773 1255 0 "I/O" )
+insert ( 3774 1255 0 "I/O" )
+insert ( 3806 1255 0 "I/O" )
+insert ( 3805 1255 0 "I/O" )
+insert ( 3804 1255 0 "I/O" )
+insert ( 3803 1255 0 "I/O" )
+insert ( 3263 1255 0 "map text array of key value pairs to jsonb object" )
+insert ( 3264 1255 0 "map text array of key value pairs to jsonb object" )
+insert ( 3787 1255 0 "map input to jsonb" )
+insert ( 3265 1255 0 "jsonb aggregate transition function" )
+insert ( 3266 1255 0 "jsonb aggregate final function" )
+insert ( 3267 1255 0 "aggregate input into jsonb" )
+insert ( 3268 1255 0 "jsonb object aggregate transition function" )
+insert ( 3269 1255 0 "jsonb object aggregate final function" )
+insert ( 3270 1255 0 "aggregate inputs into jsonb object" )
+insert ( 3271 1255 0 "build a jsonb array from any inputs" )
+insert ( 3272 1255 0 "build an empty jsonb array" )
+insert ( 3273 1255 0 "build a jsonb object from pairwise key/value inputs" )
+insert ( 3274 1255 0 "build an empty jsonb object" )
+insert ( 3262 1255 0 "remove object fields with null values from jsonb" )
+insert ( 3217 1255 0 "get value from jsonb with path elements" )
+insert ( 3940 1255 0 "get value from jsonb as text with path elements" )
+insert ( 3219 1255 0 "elements of a jsonb array" )
+insert ( 3465 1255 0 "elements of jsonb array" )
+insert ( 3207 1255 0 "length of jsonb array" )
+insert ( 3931 1255 0 "get jsonb object keys" )
+insert ( 3208 1255 0 "key value pairs of a jsonb object" )
+insert ( 3932 1255 0 "key value pairs of a jsonb object" )
+insert ( 3209 1255 0 "get record fields from a jsonb object" )
+insert ( 3475 1255 0 "get set of records with fields from a jsonb array of objects" )
+insert ( 3490 1255 0 "get record fields from a jsonb object" )
+insert ( 3491 1255 0 "get set of records with fields from a jsonb array of objects" )
+insert ( 3210 1255 0 "get the type of a jsonb value" )
+insert ( 4044 1255 0 less-equal-greater )
+insert ( 4045 1255 0 hash )
+insert ( 3416 1255 0 hash )
+insert ( 3480 1255 0 "GIN support" )
+insert ( 3482 1255 0 "GIN support" )
+insert ( 3483 1255 0 "GIN support" )
+insert ( 3484 1255 0 "GIN support" )
+insert ( 3488 1255 0 "GIN support" )
+insert ( 3485 1255 0 "GIN support" )
+insert ( 3486 1255 0 "GIN support" )
+insert ( 3487 1255 0 "GIN support" )
+insert ( 3489 1255 0 "GIN support" )
+insert ( 5054 1255 0 "Set part of a jsonb, handle NULL value" )
+insert ( 3305 1255 0 "Set part of a jsonb" )
+insert ( 3306 1255 0 "Indented text from jsonb" )
+insert ( 3579 1255 0 "Insert value into a jsonb" )
+insert ( 4001 1255 0 "I/O" )
+insert ( 4002 1255 0 "I/O" )
+insert ( 4003 1255 0 "I/O" )
+insert ( 4004 1255 0 "I/O" )
+insert ( 4005 1255 0 "jsonpath exists test" )
+insert ( 4006 1255 0 "jsonpath query" )
+insert ( 4007 1255 0 "jsonpath query wrapped into array" )
+insert ( 4008 1255 0 "jsonpath query first item" )
+insert ( 4009 1255 0 "jsonpath match" )
+insert ( 1177 1255 0 "jsonpath exists test with timezone" )
+insert ( 1179 1255 0 "jsonpath query with timezone" )
+insert ( 1180 1255 0 "jsonpath query wrapped into array with timezone" )
+insert ( 2023 1255 0 "jsonpath query first item with timezone" )
+insert ( 2030 1255 0 "jsonpath match with timezone" )
+insert ( 4010 1255 0 "implementation of @? operator" )
+insert ( 4011 1255 0 "implementation of @@ operator" )
+insert ( 2939 1255 0 "I/O" )
+insert ( 2940 1255 0 "I/O" )
+insert ( 2941 1255 0 "I/O" )
+insert ( 2942 1255 0 "I/O" )
+insert ( 2943 1255 0 "get current transaction ID" )
+insert ( 3348 1255 0 "get current transaction ID" )
+insert ( 2944 1255 0 "get current snapshot" )
+insert ( 2945 1255 0 "get xmin of snapshot" )
+insert ( 2946 1255 0 "get xmax of snapshot" )
+insert ( 2947 1255 0 "get set of in-progress txids in snapshot" )
+insert ( 2948 1255 0 "is txid visible in snapshot?" )
+insert ( 3360 1255 0 "commit status of transaction" )
+insert ( 5055 1255 0 "I/O" )
+insert ( 5056 1255 0 "I/O" )
+insert ( 5057 1255 0 "I/O" )
+insert ( 5058 1255 0 "I/O" )
+insert ( 5061 1255 0 "get current snapshot" )
+insert ( 5062 1255 0 "get xmin of snapshot" )
+insert ( 5063 1255 0 "get xmax of snapshot" )
+insert ( 5064 1255 0 "get set of in-progress transactions in snapshot" )
+insert ( 5065 1255 0 "is xid8 visible in snapshot?" )
+insert ( 5059 1255 0 "get current transaction ID" )
+insert ( 5060 1255 0 "get current transaction ID" )
+insert ( 5066 1255 0 "commit status of transaction" )
+insert ( 2987 1255 0 less-equal-greater )
+insert ( 3187 1255 0 "less-equal-greater based on byte images" )
+insert ( 5051 1255 0 "equal image" )
+insert ( 3082 1255 0 "list available extensions" )
+insert ( 3083 1255 0 "list available extension versions" )
+insert ( 3084 1255 0 "list an extension''s version update paths" )
+insert ( 3086 1255 0 "flag an extension''s table contents to be emitted by pg_dump" )
+insert ( 3100 1255 0 "row number within partition" )
+insert ( 3101 1255 0 "integer rank with gaps" )
+insert ( 3102 1255 0 "integer rank without gaps" )
+insert ( 3103 1255 0 "fractional rank within partition" )
+insert ( 3104 1255 0 "fractional row number within partition" )
+insert ( 3105 1255 0 "split rows into N groups" )
+insert ( 3106 1255 0 "fetch the preceding row value" )
+insert ( 3107 1255 0 "fetch the Nth preceding row value" )
+insert ( 3108 1255 0 "fetch the Nth preceding row value with default" )
+insert ( 3109 1255 0 "fetch the following row value" )
+insert ( 3110 1255 0 "fetch the Nth following row value" )
+insert ( 3111 1255 0 "fetch the Nth following row value with default" )
+insert ( 3112 1255 0 "fetch the first row value" )
+insert ( 3113 1255 0 "fetch the last row value" )
+insert ( 3114 1255 0 "fetch the Nth row value" )
+insert ( 3832 1255 0 "I/O" )
+insert ( 3833 1255 0 "I/O" )
+insert ( 3834 1255 0 "I/O" )
+insert ( 3835 1255 0 "I/O" )
+insert ( 3836 1255 0 "I/O" )
+insert ( 3837 1255 0 "I/O" )
+insert ( 3848 1255 0 "lower bound of range" )
+insert ( 3849 1255 0 "upper bound of range" )
+insert ( 3850 1255 0 "is the range empty?" )
+insert ( 3851 1255 0 "is the range''s lower bound inclusive?" )
+insert ( 3852 1255 0 "is the range''s upper bound inclusive?" )
+insert ( 3853 1255 0 "is the range''s lower bound infinite?" )
+insert ( 3854 1255 0 "is the range''s upper bound infinite?" )
+insert ( 4057 1255 0 "the smallest range which includes both of the given ranges" )
+insert ( 3870 1255 0 less-equal-greater )
+insert ( 3875 1255 0 "GiST support" )
+insert ( 3876 1255 0 "GiST support" )
+insert ( 3879 1255 0 "GiST support" )
+insert ( 3880 1255 0 "GiST support" )
+insert ( 3881 1255 0 "GiST support" )
+insert ( 3902 1255 0 "hash a range" )
+insert ( 3417 1255 0 "hash a range" )
+insert ( 3916 1255 0 "range typanalyze" )
+insert ( 3169 1255 0 "restriction selectivity for range operators" )
+insert ( 3914 1255 0 "convert an int4 range to canonical form" )
+insert ( 3928 1255 0 "convert an int8 range to canonical form" )
+insert ( 3915 1255 0 "convert a date range to canonical form" )
+insert ( 3922 1255 0 "float8 difference of two int4 values" )
+insert ( 3923 1255 0 "float8 difference of two int8 values" )
+insert ( 3924 1255 0 "float8 difference of two numeric values" )
+insert ( 3925 1255 0 "float8 difference of two date values" )
+insert ( 3929 1255 0 "float8 difference of two timestamp values" )
+insert ( 3930 1255 0 "float8 difference of two timestamp with time zone values" )
+insert ( 3840 1255 0 "int4range constructor" )
+insert ( 3841 1255 0 "int4range constructor" )
+insert ( 3844 1255 0 "numrange constructor" )
+insert ( 3845 1255 0 "numrange constructor" )
+insert ( 3933 1255 0 "tsrange constructor" )
+insert ( 3934 1255 0 "tsrange constructor" )
+insert ( 3937 1255 0 "tstzrange constructor" )
+insert ( 3938 1255 0 "tstzrange constructor" )
+insert ( 3941 1255 0 "daterange constructor" )
+insert ( 3942 1255 0 "daterange constructor" )
+insert ( 3945 1255 0 "int8range constructor" )
+insert ( 3946 1255 0 "int8range constructor" )
+insert ( 3846 1255 0 "construct date" )
+insert ( 3847 1255 0 "construct time" )
+insert ( 3461 1255 0 "construct timestamp" )
+insert ( 3462 1255 0 "construct timestamp with time zone" )
+insert ( 3463 1255 0 "construct timestamp with time zone" )
+insert ( 3464 1255 0 "construct interval" )
+insert ( 4018 1255 0 "SP-GiST support for quad tree over point" )
+insert ( 4019 1255 0 "SP-GiST support for quad tree over point" )
+insert ( 4020 1255 0 "SP-GiST support for quad tree over point" )
+insert ( 4021 1255 0 "SP-GiST support for quad tree over point" )
+insert ( 4022 1255 0 "SP-GiST support for quad tree and k-d tree over point" )
+insert ( 4023 1255 0 "SP-GiST support for k-d tree over point" )
+insert ( 4024 1255 0 "SP-GiST support for k-d tree over point" )
+insert ( 4025 1255 0 "SP-GiST support for k-d tree over point" )
+insert ( 4026 1255 0 "SP-GiST support for k-d tree over point" )
+insert ( 4027 1255 0 "SP-GiST support for radix tree over text" )
+insert ( 4028 1255 0 "SP-GiST support for radix tree over text" )
+insert ( 4029 1255 0 "SP-GiST support for radix tree over text" )
+insert ( 4030 1255 0 "SP-GiST support for radix tree over text" )
+insert ( 4031 1255 0 "SP-GiST support for radix tree over text" )
+insert ( 3469 1255 0 "SP-GiST support for quad tree over range" )
+insert ( 3470 1255 0 "SP-GiST support for quad tree over range" )
+insert ( 3471 1255 0 "SP-GiST support for quad tree over range" )
+insert ( 3472 1255 0 "SP-GiST support for quad tree over range" )
+insert ( 3473 1255 0 "SP-GiST support for quad tree over range" )
+insert ( 5012 1255 0 "SP-GiST support for quad tree over box" )
+insert ( 5013 1255 0 "SP-GiST support for quad tree over box" )
+insert ( 5014 1255 0 "SP-GiST support for quad tree over box" )
+insert ( 5015 1255 0 "SP-GiST support for quad tree over box" )
+insert ( 5016 1255 0 "SP-GiST support for quad tree over box" )
+insert ( 5010 1255 0 "SP-GiST support for quad tree over 2-D types represented by their bounding boxes" )
+insert ( 5011 1255 0 "SP-GiST support for quad tree over polygons" )
+insert ( 3779 1255 0 "create a physical replication slot" )
+insert ( 4220 1255 0 "copy a physical replication slot, changing temporality" )
+insert ( 4221 1255 0 "copy a physical replication slot" )
+insert ( 3780 1255 0 "drop a replication slot" )
+insert ( 3781 1255 0 "information about replication slots currently in use" )
+insert ( 3786 1255 0 "set up a logical replication slot" )
+insert ( 4222 1255 0 "copy a logical replication slot, changing temporality and plugin" )
+insert ( 4223 1255 0 "copy a logical replication slot, changing temporality" )
+insert ( 4224 1255 0 "copy a logical replication slot" )
+insert ( 3782 1255 0 "get changes from replication slot" )
+insert ( 3783 1255 0 "get binary changes from replication slot" )
+insert ( 3784 1255 0 "peek at changes from replication slot" )
+insert ( 3785 1255 0 "peek at binary changes from replication slot" )
+insert ( 3878 1255 0 "advance logical replication slot" )
+insert ( 3577 1255 0 "emit a textual logical decoding message" )
+insert ( 3578 1255 0 "emit a binary logical decoding message" )
+insert ( 3566 1255 0 "list objects dropped by the current command" )
+insert ( 4566 1255 0 "return Oid of the table getting rewritten" )
+insert ( 4567 1255 0 "return reason code for table getting rewritten" )
+insert ( 4568 1255 0 "list DDL actions being executed by the current command" )
+insert ( 3970 1255 0 "aggregate transition function" )
+insert ( 3971 1255 0 "aggregate transition function" )
+insert ( 3972 1255 0 "discrete percentile" )
+insert ( 3973 1255 0 "aggregate final function" )
+insert ( 3974 1255 0 "continuous distribution percentile" )
+insert ( 3975 1255 0 "aggregate final function" )
+insert ( 3976 1255 0 "continuous distribution percentile" )
+insert ( 3977 1255 0 "aggregate final function" )
+insert ( 3978 1255 0 "multiple discrete percentiles" )
+insert ( 3979 1255 0 "aggregate final function" )
+insert ( 3980 1255 0 "multiple continuous percentiles" )
+insert ( 3981 1255 0 "aggregate final function" )
+insert ( 3982 1255 0 "multiple continuous percentiles" )
+insert ( 3983 1255 0 "aggregate final function" )
+insert ( 3984 1255 0 "most common value" )
+insert ( 3985 1255 0 "aggregate final function" )
+insert ( 3986 1255 0 "rank of hypothetical row" )
+insert ( 3987 1255 0 "aggregate final function" )
+insert ( 3988 1255 0 "fractional rank of hypothetical row" )
+insert ( 3989 1255 0 "aggregate final function" )
+insert ( 3990 1255 0 "cumulative distribution of hypothetical row" )
+insert ( 3991 1255 0 "aggregate final function" )
+insert ( 3992 1255 0 "rank of hypothetical row without gaps" )
+insert ( 3993 1255 0 "aggregate final function" )
+insert ( 3582 1255 0 "for use by pg_upgrade" )
+insert ( 3584 1255 0 "for use by pg_upgrade" )
+insert ( 3585 1255 0 "for use by pg_upgrade" )
+insert ( 3586 1255 0 "for use by pg_upgrade" )
+insert ( 3587 1255 0 "for use by pg_upgrade" )
+insert ( 3588 1255 0 "for use by pg_upgrade" )
+insert ( 3589 1255 0 "for use by pg_upgrade" )
+insert ( 3590 1255 0 "for use by pg_upgrade" )
+insert ( 3591 1255 0 "for use by pg_upgrade" )
+insert ( 4083 1255 0 "for use by pg_upgrade" )
+insert ( 4101 1255 0 "for use by pg_upgrade" )
+insert ( 4302 1255 0 "internal conversion function for KOI8R to MULE_INTERNAL" )
+insert ( 4303 1255 0 "internal conversion function for MULE_INTERNAL to KOI8R" )
+insert ( 4304 1255 0 "internal conversion function for ISO-8859-5 to MULE_INTERNAL" )
+insert ( 4305 1255 0 "internal conversion function for MULE_INTERNAL to ISO-8859-5" )
+insert ( 4306 1255 0 "internal conversion function for WIN1251 to MULE_INTERNAL" )
+insert ( 4307 1255 0 "internal conversion function for MULE_INTERNAL to WIN1251" )
+insert ( 4308 1255 0 "internal conversion function for WIN866 to MULE_INTERNAL" )
+insert ( 4309 1255 0 "internal conversion function for MULE_INTERNAL to WIN866" )
+insert ( 4310 1255 0 "internal conversion function for KOI8R to WIN1251" )
+insert ( 4311 1255 0 "internal conversion function for WIN1251 to KOI8R" )
+insert ( 4312 1255 0 "internal conversion function for KOI8R to WIN866" )
+insert ( 4313 1255 0 "internal conversion function for WIN866 to KOI8R" )
+insert ( 4314 1255 0 "internal conversion function for WIN866 to WIN1251" )
+insert ( 4315 1255 0 "internal conversion function for WIN1251 to WIN866" )
+insert ( 4316 1255 0 "internal conversion function for ISO-8859-5 to KOI8R" )
+insert ( 4317 1255 0 "internal conversion function for KOI8R to ISO-8859-5" )
+insert ( 4318 1255 0 "internal conversion function for ISO-8859-5 to WIN1251" )
+insert ( 4319 1255 0 "internal conversion function for WIN1251 to ISO-8859-5" )
+insert ( 4320 1255 0 "internal conversion function for ISO-8859-5 to WIN866" )
+insert ( 4321 1255 0 "internal conversion function for WIN866 to ISO-8859-5" )
+insert ( 4322 1255 0 "internal conversion function for EUC_CN to MULE_INTERNAL" )
+insert ( 4323 1255 0 "internal conversion function for MULE_INTERNAL to EUC_CN" )
+insert ( 4324 1255 0 "internal conversion function for EUC_JP to SJIS" )
+insert ( 4325 1255 0 "internal conversion function for SJIS to EUC_JP" )
+insert ( 4326 1255 0 "internal conversion function for EUC_JP to MULE_INTERNAL" )
+insert ( 4327 1255 0 "internal conversion function for SJIS to MULE_INTERNAL" )
+insert ( 4328 1255 0 "internal conversion function for MULE_INTERNAL to EUC_JP" )
+insert ( 4329 1255 0 "internal conversion function for MULE_INTERNAL to SJIS" )
+insert ( 4330 1255 0 "internal conversion function for EUC_KR to MULE_INTERNAL" )
+insert ( 4331 1255 0 "internal conversion function for MULE_INTERNAL to EUC_KR" )
+insert ( 4332 1255 0 "internal conversion function for EUC_TW to BIG5" )
+insert ( 4333 1255 0 "internal conversion function for BIG5 to EUC_TW" )
+insert ( 4334 1255 0 "internal conversion function for EUC_TW to MULE_INTERNAL" )
+insert ( 4335 1255 0 "internal conversion function for BIG5 to MULE_INTERNAL" )
+insert ( 4336 1255 0 "internal conversion function for MULE_INTERNAL to EUC_TW" )
+insert ( 4337 1255 0 "internal conversion function for MULE_INTERNAL to BIG5" )
+insert ( 4338 1255 0 "internal conversion function for LATIN2 to MULE_INTERNAL" )
+insert ( 4339 1255 0 "internal conversion function for MULE_INTERNAL to LATIN2" )
+insert ( 4340 1255 0 "internal conversion function for WIN1250 to MULE_INTERNAL" )
+insert ( 4341 1255 0 "internal conversion function for MULE_INTERNAL to WIN1250" )
+insert ( 4342 1255 0 "internal conversion function for LATIN2 to WIN1250" )
+insert ( 4343 1255 0 "internal conversion function for WIN1250 to LATIN2" )
+insert ( 4344 1255 0 "internal conversion function for LATIN1 to MULE_INTERNAL" )
+insert ( 4345 1255 0 "internal conversion function for MULE_INTERNAL to LATIN1" )
+insert ( 4346 1255 0 "internal conversion function for LATIN3 to MULE_INTERNAL" )
+insert ( 4347 1255 0 "internal conversion function for MULE_INTERNAL to LATIN3" )
+insert ( 4348 1255 0 "internal conversion function for LATIN4 to MULE_INTERNAL" )
+insert ( 4349 1255 0 "internal conversion function for MULE_INTERNAL to LATIN4" )
+insert ( 4352 1255 0 "internal conversion function for BIG5 to UTF8" )
+insert ( 4353 1255 0 "internal conversion function for UTF8 to BIG5" )
+insert ( 4354 1255 0 "internal conversion function for UTF8 to KOI8R" )
+insert ( 4355 1255 0 "internal conversion function for KOI8R to UTF8" )
+insert ( 4356 1255 0 "internal conversion function for UTF8 to KOI8U" )
+insert ( 4357 1255 0 "internal conversion function for KOI8U to UTF8" )
+insert ( 4358 1255 0 "internal conversion function for UTF8 to WIN" )
+insert ( 4359 1255 0 "internal conversion function for WIN to UTF8" )
+insert ( 4360 1255 0 "internal conversion function for EUC_CN to UTF8" )
+insert ( 4361 1255 0 "internal conversion function for UTF8 to EUC_CN" )
+insert ( 4362 1255 0 "internal conversion function for EUC_JP to UTF8" )
+insert ( 4363 1255 0 "internal conversion function for UTF8 to EUC_JP" )
+insert ( 4364 1255 0 "internal conversion function for EUC_KR to UTF8" )
+insert ( 4365 1255 0 "internal conversion function for UTF8 to EUC_KR" )
+insert ( 4366 1255 0 "internal conversion function for EUC_TW to UTF8" )
+insert ( 4367 1255 0 "internal conversion function for UTF8 to EUC_TW" )
+insert ( 4368 1255 0 "internal conversion function for GB18030 to UTF8" )
+insert ( 4369 1255 0 "internal conversion function for UTF8 to GB18030" )
+insert ( 4370 1255 0 "internal conversion function for GBK to UTF8" )
+insert ( 4371 1255 0 "internal conversion function for UTF8 to GBK" )
+insert ( 4372 1255 0 "internal conversion function for UTF8 to ISO-8859 2-16" )
+insert ( 4373 1255 0 "internal conversion function for ISO-8859 2-16 to UTF8" )
+insert ( 4374 1255 0 "internal conversion function for LATIN1 to UTF8" )
+insert ( 4375 1255 0 "internal conversion function for UTF8 to LATIN1" )
+insert ( 4376 1255 0 "internal conversion function for JOHAB to UTF8" )
+insert ( 4377 1255 0 "internal conversion function for UTF8 to JOHAB" )
+insert ( 4378 1255 0 "internal conversion function for SJIS to UTF8" )
+insert ( 4379 1255 0 "internal conversion function for UTF8 to SJIS" )
+insert ( 4380 1255 0 "internal conversion function for UHC to UTF8" )
+insert ( 4381 1255 0 "internal conversion function for UTF8 to UHC" )
+insert ( 4382 1255 0 "internal conversion function for EUC_JIS_2004 to UTF8" )
+insert ( 4383 1255 0 "internal conversion function for UTF8 to EUC_JIS_2004" )
+insert ( 4384 1255 0 "internal conversion function for SHIFT_JIS_2004 to UTF8" )
+insert ( 4385 1255 0 "internal conversion function for UTF8 to SHIFT_JIS_2004" )
+insert ( 4386 1255 0 "internal conversion function for EUC_JIS_2004 to SHIFT_JIS_2004" )
+insert ( 4387 1255 0 "internal conversion function for SHIFT_JIS_2004 to EUC_JIS_2004" )
+insert ( 5040 1255 0 "restriction selectivity for generic matching operators" )
+insert ( 5041 1255 0 "join selectivity for generic matching operators" )
+insert ( 6003 1255 0 "create a replication origin" )
+insert ( 6004 1255 0 "drop replication origin identified by its name" )
+insert ( 6005 1255 0 "translate the replication origin''s name to its id" )
+insert ( 6006 1255 0 "configure session to maintain replication progress tracking for the passed in origin" )
+insert ( 6007 1255 0 "teardown configured replication progress tracking" )
+insert ( 6008 1255 0 "is a replication origin configured in this session" )
+insert ( 6009 1255 0 "get the replication progress of the current session" )
+insert ( 6010 1255 0 "setup the transaction''s origin lsn and timestamp" )
+insert ( 6011 1255 0 "reset the transaction''s origin lsn and timestamp" )
+insert ( 6012 1255 0 "advance replication origin to specific location" )
+insert ( 6013 1255 0 "get an individual replication origin''s replication progress" )
+insert ( 6014 1255 0 "get progress for all replication origins" )
+insert ( 6119 1255 0 "get OIDs of tables in a publication" )
+insert ( 6121 1255 0 "returns whether a relation can be part of a publication" )
+insert ( 3298 1255 0 "row security for current context active on table by table oid" )
+insert ( 3299 1255 0 "row security for current context active on table by table name" )
+insert ( 3400 1255 0 "pg_config binary as a function" )
+insert ( 3441 1255 0 "pg_controldata general state information as a function" )
+insert ( 3442 1255 0 "pg_controldata checkpoint state information as a function" )
+insert ( 3443 1255 0 "pg_controldata recovery state information as a function" )
+insert ( 3444 1255 0 "pg_controldata init state information as a function" )
+insert ( 3445 1255 0 "import collations from operating system" )
+insert ( 3448 1255 0 "get actual version of collation from operating system" )
+insert ( 3353 1255 0 "list files in the log directory" )
+insert ( 3354 1255 0 "list of files in the WAL directory" )
+insert ( 5031 1255 0 "list of files in the archive_status directory" )
+insert ( 5029 1255 0 "list files in the pgsql_tmp directory" )
+insert ( 5030 1255 0 "list files in the pgsql_tmp directory" )
+insert ( 5028 1255 0 "hash partition CHECK constraint" )
+insert ( 3423 1255 0 "view partition tree tables" )
+insert ( 3425 1255 0 "view ancestors of the partition" )
+insert ( 3424 1255 0 "get top-most partition root parent" )
+insert ( 4350 1255 0 "Unicode normalization" )
+insert ( 4351 1255 0 "check Unicode normalization" )
+insert ( 16 1247 0 "boolean, ''true''/''false''" )
+insert ( 17 1247 0 "variable-length string, binary values escaped" )
+insert ( 18 1247 0 "single character" )
+insert ( 19 1247 0 "63-byte type for storing system identifiers" )
+insert ( 20 1247 0 "~18 digit integer, 8-byte storage" )
+insert ( 21 1247 0 "-32 thousand to 32 thousand, 2-byte storage" )
+insert ( 22 1247 0 "array of int2, used in system tables" )
+insert ( 23 1247 0 "-2 billion to 2 billion integer, 4-byte storage" )
+insert ( 24 1247 0 "registered procedure" )
+insert ( 25 1247 0 "variable-length string, no limit specified" )
+insert ( 26 1247 0 "object identifier(oid), maximum 4 billion" )
+insert ( 27 1247 0 "(block, offset), physical location of tuple" )
+insert ( 28 1247 0 "transaction id" )
+insert ( 29 1247 0 "command identifier type, sequence in transaction id" )
+insert ( 30 1247 0 "array of oids, used in system tables" )
+insert ( 114 1247 0 "JSON stored as text" )
+insert ( 142 1247 0 "XML content" )
+insert ( 194 1247 0 "string representing an internal node tree" )
+insert ( 3361 1247 0 "multivariate ndistinct coefficients" )
+insert ( 3402 1247 0 "multivariate dependencies" )
+insert ( 5017 1247 0 "multivariate MCV list" )
+insert ( 32 1247 0 "internal type for passing CollectedCommand" )
+insert ( 5069 1247 0 "full transaction id" )
+insert ( 600 1247 0 "geometric point ''(x, y)''" )
+insert ( 601 1247 0 "geometric line segment ''(pt1,pt2)''" )
+insert ( 602 1247 0 "geometric path ''(pt1,...)''" )
+insert ( 603 1247 0 "geometric box ''(lower left,upper right)''" )
+insert ( 604 1247 0 "geometric polygon ''(pt1,...)''" )
+insert ( 628 1247 0 "geometric line" )
+insert ( 700 1247 0 "single-precision floating point number, 4-byte storage" )
+insert ( 701 1247 0 "double-precision floating point number, 8-byte storage" )
+insert ( 705 1247 0 "pseudo-type representing an undetermined type" )
+insert ( 718 1247 0 "geometric circle ''(center,radius)''" )
+insert ( 790 1247 0 "monetary amounts, $d,ddd.cc" )
+insert ( 829 1247 0 "XX:XX:XX:XX:XX:XX, MAC address" )
+insert ( 869 1247 0 "IP address/netmask, host address, netmask optional" )
+insert ( 650 1247 0 "network IP address/netmask, network address" )
+insert ( 774 1247 0 "XX:XX:XX:XX:XX:XX:XX:XX, MAC address" )
+insert ( 1033 1247 0 "access control list" )
+insert ( 1042 1247 0 "char(length), blank-padded string, fixed storage length" )
+insert ( 1043 1247 0 "varchar(length), non-blank-padded string, variable storage length" )
+insert ( 1082 1247 0 date )
+insert ( 1083 1247 0 "time of day" )
+insert ( 1114 1247 0 "date and time" )
+insert ( 1184 1247 0 "date and time with time zone" )
+insert ( 1186 1247 0 "@ <number> <units>, time interval" )
+insert ( 1266 1247 0 "time of day with time zone" )
+insert ( 1560 1247 0 "fixed-length bit string" )
+insert ( 1562 1247 0 "variable-length bit string" )
+insert ( 1700 1247 0 "numeric(precision, decimal), arbitrary precision number" )
+insert ( 1790 1247 0 "reference to cursor (portal name)" )
+insert ( 2202 1247 0 "registered procedure (with args)" )
+insert ( 2203 1247 0 "registered operator" )
+insert ( 2204 1247 0 "registered operator (with args)" )
+insert ( 2205 1247 0 "registered class" )
+insert ( 4191 1247 0 "registered collation" )
+insert ( 2206 1247 0 "registered type" )
+insert ( 4096 1247 0 "registered role" )
+insert ( 4089 1247 0 "registered namespace" )
+insert ( 2950 1247 0 "UUID datatype" )
+insert ( 3220 1247 0 "PostgreSQL LSN datatype" )
+insert ( 3614 1247 0 "text representation for text search" )
+insert ( 3642 1247 0 "GiST index internal text representation for text search" )
+insert ( 3615 1247 0 "query representation for text search" )
+insert ( 3734 1247 0 "registered text search configuration" )
+insert ( 3769 1247 0 "registered text search dictionary" )
+insert ( 3802 1247 0 "Binary JSON" )
+insert ( 4072 1247 0 "JSON path" )
+insert ( 2970 1247 0 "txid snapshot" )
+insert ( 5038 1247 0 snapshot )
+insert ( 3904 1247 0 "range of integers" )
+insert ( 3906 1247 0 "range of numerics" )
+insert ( 3908 1247 0 "range of timestamps without time zone" )
+insert ( 3910 1247 0 "range of timestamps with time zone" )
+insert ( 3912 1247 0 "range of dates" )
+insert ( 3926 1247 0 "range of bigints" )
+insert ( 2249 1247 0 "pseudo-type representing any composite type" )
+insert ( 2275 1247 0 "C-style string" )
+insert ( 2276 1247 0 "pseudo-type representing any type" )
+insert ( 2277 1247 0 "pseudo-type representing a polymorphic array type" )
+insert ( 2278 1247 0 "pseudo-type for the result of a function with no real result" )
+insert ( 2279 1247 0 "pseudo-type for the result of a trigger function" )
+insert ( 3838 1247 0 "pseudo-type for the result of an event trigger function" )
+insert ( 2280 1247 0 "pseudo-type for the result of a language handler function" )
+insert ( 2281 1247 0 "pseudo-type representing an internal data structure" )
+insert ( 2283 1247 0 "pseudo-type representing a polymorphic base type" )
+insert ( 2776 1247 0 "pseudo-type representing a polymorphic base type that is not an array" )
+insert ( 3500 1247 0 "pseudo-type representing a polymorphic base type that is an enum" )
+insert ( 3115 1247 0 "pseudo-type for the result of an FDW handler function" )
+insert ( 325 1247 0 "pseudo-type for the result of an index AM handler function" )
+insert ( 3310 1247 0 "pseudo-type for the result of a tablesample method function" )
+insert ( 3831 1247 0 "pseudo-type representing a range over a polymorphic base type" )
+insert ( 5077 1247 0 "pseudo-type representing a polymorphic common type" )
+insert ( 5078 1247 0 "pseudo-type representing an array of polymorphic common type elements" )
+insert ( 5079 1247 0 "pseudo-type representing a polymorphic common type that is not an array" )
+insert ( 5080 1247 0 "pseudo-type representing a range over a polymorphic common type" )
+insert ( 15 2617 0 equal )
+insert ( 36 2617 0 "not equal" )
+insert ( 37 2617 0 "less than" )
+insert ( 76 2617 0 "greater than" )
+insert ( 80 2617 0 "less than or equal" )
+insert ( 82 2617 0 "greater than or equal" )
+insert ( 58 2617 0 "less than" )
+insert ( 59 2617 0 "greater than" )
+insert ( 85 2617 0 "not equal" )
+insert ( 91 2617 0 equal )
+insert ( 1694 2617 0 "less than or equal" )
+insert ( 1695 2617 0 "greater than or equal" )
+insert ( 92 2617 0 equal )
+insert ( 93 2617 0 equal )
+insert ( 94 2617 0 equal )
+insert ( 95 2617 0 "less than" )
+insert ( 96 2617 0 equal )
+insert ( 97 2617 0 "less than" )
+insert ( 98 2617 0 equal )
+insert ( 3877 2617 0 "starts with" )
+insert ( 254 2617 0 equal )
+insert ( 255 2617 0 "less than" )
+insert ( 256 2617 0 "less than or equal" )
+insert ( 257 2617 0 "greater than or equal" )
+insert ( 258 2617 0 "greater than" )
+insert ( 259 2617 0 "not equal" )
+insert ( 260 2617 0 equal )
+insert ( 261 2617 0 "less than" )
+insert ( 262 2617 0 "less than or equal" )
+insert ( 263 2617 0 "greater than or equal" )
+insert ( 264 2617 0 "greater than" )
+insert ( 265 2617 0 "not equal" )
+insert ( 349 2617 0 "append element onto end of array" )
+insert ( 374 2617 0 "prepend element onto front of array" )
+insert ( 375 2617 0 concatenate )
+insert ( 352 2617 0 equal )
+insert ( 353 2617 0 equal )
+insert ( 3315 2617 0 "not equal" )
+insert ( 3316 2617 0 "not equal" )
+insert ( 5068 2617 0 equal )
+insert ( 5072 2617 0 "not equal" )
+insert ( 5073 2617 0 "less than" )
+insert ( 5074 2617 0 "greater than" )
+insert ( 5075 2617 0 "less than or equal" )
+insert ( 5076 2617 0 "greater than or equal" )
+insert ( 388 2617 0 "deprecated, use factorial() instead" )
+insert ( 389 2617 0 "deprecated, use factorial() instead" )
+insert ( 385 2617 0 equal )
+insert ( 387 2617 0 equal )
+insert ( 402 2617 0 "not equal" )
+insert ( 2799 2617 0 "less than" )
+insert ( 2800 2617 0 "greater than" )
+insert ( 2801 2617 0 "less than or equal" )
+insert ( 2802 2617 0 "greater than or equal" )
+insert ( 410 2617 0 equal )
+insert ( 411 2617 0 "not equal" )
+insert ( 412 2617 0 "less than" )
+insert ( 413 2617 0 "greater than" )
+insert ( 414 2617 0 "less than or equal" )
+insert ( 415 2617 0 "greater than or equal" )
+insert ( 416 2617 0 equal )
+insert ( 417 2617 0 "not equal" )
+insert ( 418 2617 0 "less than" )
+insert ( 419 2617 0 "greater than" )
+insert ( 420 2617 0 "less than or equal" )
+insert ( 430 2617 0 "greater than or equal" )
+insert ( 439 2617 0 modulus )
+insert ( 473 2617 0 "absolute value" )
+insert ( 484 2617 0 negate )
+insert ( 485 2617 0 "is left of" )
+insert ( 486 2617 0 "overlaps or is left of" )
+insert ( 487 2617 0 "overlaps or is right of" )
+insert ( 488 2617 0 "is right of" )
+insert ( 489 2617 0 "is contained by" )
+insert ( 490 2617 0 contains )
+insert ( 491 2617 0 "same as" )
+insert ( 492 2617 0 overlaps )
+insert ( 493 2617 0 "is left of" )
+insert ( 494 2617 0 "overlaps or is left of" )
+insert ( 495 2617 0 "overlaps or is right of" )
+insert ( 496 2617 0 "is right of" )
+insert ( 497 2617 0 "is contained by" )
+insert ( 498 2617 0 contains )
+insert ( 499 2617 0 "same as" )
+insert ( 500 2617 0 overlaps )
+insert ( 501 2617 0 "greater than or equal by area" )
+insert ( 502 2617 0 "greater than by area" )
+insert ( 503 2617 0 "equal by area" )
+insert ( 504 2617 0 "less than by area" )
+insert ( 505 2617 0 "less than or equal by area" )
+insert ( 506 2617 0 "is above" )
+insert ( 507 2617 0 "is left of" )
+insert ( 508 2617 0 "is right of" )
+insert ( 509 2617 0 "is below" )
+insert ( 510 2617 0 "same as" )
+insert ( 511 2617 0 "point inside box" )
+insert ( 433 2617 0 contains )
+insert ( 512 2617 0 "point within closed path, or point on open path" )
+insert ( 513 2617 0 "center of" )
+insert ( 514 2617 0 multiply )
+insert ( 517 2617 0 "distance between" )
+insert ( 518 2617 0 "not equal" )
+insert ( 519 2617 0 "not equal" )
+insert ( 520 2617 0 "greater than" )
+insert ( 521 2617 0 "greater than" )
+insert ( 522 2617 0 "less than or equal" )
+insert ( 523 2617 0 "less than or equal" )
+insert ( 524 2617 0 "greater than or equal" )
+insert ( 525 2617 0 "greater than or equal" )
+insert ( 526 2617 0 multiply )
+insert ( 527 2617 0 divide )
+insert ( 528 2617 0 divide )
+insert ( 529 2617 0 modulus )
+insert ( 530 2617 0 modulus )
+insert ( 531 2617 0 "not equal" )
+insert ( 532 2617 0 equal )
+insert ( 533 2617 0 equal )
+insert ( 534 2617 0 "less than" )
+insert ( 535 2617 0 "less than" )
+insert ( 536 2617 0 "greater than" )
+insert ( 537 2617 0 "greater than" )
+insert ( 538 2617 0 "not equal" )
+insert ( 539 2617 0 "not equal" )
+insert ( 540 2617 0 "less than or equal" )
+insert ( 541 2617 0 "less than or equal" )
+insert ( 542 2617 0 "greater than or equal" )
+insert ( 543 2617 0 "greater than or equal" )
+insert ( 544 2617 0 multiply )
+insert ( 545 2617 0 multiply )
+insert ( 546 2617 0 divide )
+insert ( 547 2617 0 divide )
+insert ( 550 2617 0 add )
+insert ( 551 2617 0 add )
+insert ( 552 2617 0 add )
+insert ( 553 2617 0 add )
+insert ( 554 2617 0 subtract )
+insert ( 555 2617 0 subtract )
+insert ( 556 2617 0 subtract )
+insert ( 557 2617 0 subtract )
+insert ( 558 2617 0 negate )
+insert ( 559 2617 0 negate )
+insert ( 584 2617 0 negate )
+insert ( 585 2617 0 negate )
+insert ( 586 2617 0 add )
+insert ( 587 2617 0 subtract )
+insert ( 588 2617 0 divide )
+insert ( 589 2617 0 multiply )
+insert ( 590 2617 0 "absolute value" )
+insert ( 591 2617 0 add )
+insert ( 592 2617 0 subtract )
+insert ( 593 2617 0 divide )
+insert ( 594 2617 0 multiply )
+insert ( 595 2617 0 "absolute value" )
+insert ( 596 2617 0 "square root" )
+insert ( 597 2617 0 "cube root" )
+insert ( 607 2617 0 equal )
+insert ( 608 2617 0 "not equal" )
+insert ( 609 2617 0 "less than" )
+insert ( 610 2617 0 "greater than" )
+insert ( 611 2617 0 "less than or equal" )
+insert ( 612 2617 0 "greater than or equal" )
+insert ( 644 2617 0 "not equal" )
+insert ( 645 2617 0 "less than" )
+insert ( 646 2617 0 "greater than" )
+insert ( 647 2617 0 "less than or equal" )
+insert ( 648 2617 0 "greater than or equal" )
+insert ( 649 2617 0 equal )
+insert ( 613 2617 0 "distance between" )
+insert ( 760 2617 0 "distance between" )
+insert ( 614 2617 0 "distance between" )
+insert ( 761 2617 0 "distance between" )
+insert ( 615 2617 0 "distance between" )
+insert ( 606 2617 0 "distance between" )
+insert ( 616 2617 0 "distance between" )
+insert ( 762 2617 0 "distance between" )
+insert ( 617 2617 0 "distance between" )
+insert ( 763 2617 0 "distance between" )
+insert ( 618 2617 0 "distance between" )
+insert ( 784 2617 0 "distance between" )
+insert ( 620 2617 0 equal )
+insert ( 621 2617 0 "not equal" )
+insert ( 622 2617 0 "less than" )
+insert ( 623 2617 0 "greater than" )
+insert ( 624 2617 0 "less than or equal" )
+insert ( 625 2617 0 "greater than or equal" )
+insert ( 630 2617 0 "not equal" )
+insert ( 631 2617 0 "less than" )
+insert ( 632 2617 0 "less than or equal" )
+insert ( 633 2617 0 "greater than" )
+insert ( 634 2617 0 "greater than or equal" )
+insert ( 639 2617 0 "matches regular expression, case-sensitive" )
+insert ( 640 2617 0 "does not match regular expression, case-sensitive" )
+insert ( 641 2617 0 "matches regular expression, case-sensitive" )
+insert ( 642 2617 0 "does not match regular expression, case-sensitive" )
+insert ( 643 2617 0 "not equal" )
+insert ( 654 2617 0 concatenate )
+insert ( 660 2617 0 "less than" )
+insert ( 661 2617 0 "less than or equal" )
+insert ( 662 2617 0 "greater than" )
+insert ( 663 2617 0 "greater than or equal" )
+insert ( 664 2617 0 "less than" )
+insert ( 665 2617 0 "less than or equal" )
+insert ( 666 2617 0 "greater than" )
+insert ( 667 2617 0 "greater than or equal" )
+insert ( 670 2617 0 equal )
+insert ( 671 2617 0 "not equal" )
+insert ( 672 2617 0 "less than" )
+insert ( 673 2617 0 "less than or equal" )
+insert ( 674 2617 0 "greater than" )
+insert ( 675 2617 0 "greater than or equal" )
+insert ( 682 2617 0 "absolute value" )
+insert ( 684 2617 0 add )
+insert ( 685 2617 0 subtract )
+insert ( 686 2617 0 multiply )
+insert ( 687 2617 0 divide )
+insert ( 688 2617 0 add )
+insert ( 689 2617 0 subtract )
+insert ( 690 2617 0 multiply )
+insert ( 691 2617 0 divide )
+insert ( 692 2617 0 add )
+insert ( 693 2617 0 subtract )
+insert ( 694 2617 0 multiply )
+insert ( 695 2617 0 divide )
+insert ( 818 2617 0 add )
+insert ( 819 2617 0 subtract )
+insert ( 820 2617 0 multiply )
+insert ( 821 2617 0 divide )
+insert ( 822 2617 0 add )
+insert ( 823 2617 0 subtract )
+insert ( 824 2617 0 multiply )
+insert ( 825 2617 0 divide )
+insert ( 706 2617 0 "distance between" )
+insert ( 707 2617 0 "distance between" )
+insert ( 708 2617 0 "distance between" )
+insert ( 709 2617 0 "distance between" )
+insert ( 712 2617 0 "distance between" )
+insert ( 713 2617 0 "not equal" )
+insert ( 731 2617 0 "add points (translate)" )
+insert ( 732 2617 0 "subtract points (translate)" )
+insert ( 733 2617 0 "multiply points (scale/rotate)" )
+insert ( 734 2617 0 "divide points (scale/rotate)" )
+insert ( 735 2617 0 concatenate )
+insert ( 736 2617 0 "add (translate path)" )
+insert ( 737 2617 0 "subtract (translate path)" )
+insert ( 738 2617 0 "multiply (rotate/scale path)" )
+insert ( 739 2617 0 "divide (rotate/scale path)" )
+insert ( 755 2617 0 contains )
+insert ( 756 2617 0 "is contained by" )
+insert ( 757 2617 0 contains )
+insert ( 758 2617 0 "is contained by" )
+insert ( 759 2617 0 contains )
+insert ( 773 2617 0 "absolute value" )
+insert ( 792 2617 0 equal )
+insert ( 793 2617 0 "less than" )
+insert ( 794 2617 0 "greater than" )
+insert ( 795 2617 0 "less than or equal" )
+insert ( 796 2617 0 "greater than or equal" )
+insert ( 797 2617 0 "number of points" )
+insert ( 798 2617 0 intersect )
+insert ( 799 2617 0 "sum of path segment lengths" )
+insert ( 800 2617 0 "is above (allows touching)" )
+insert ( 801 2617 0 "is below (allows touching)" )
+insert ( 802 2617 0 "deprecated, use && instead" )
+insert ( 803 2617 0 "box intersection" )
+insert ( 804 2617 0 "add point to box (translate)" )
+insert ( 805 2617 0 "subtract point from box (translate)" )
+insert ( 806 2617 0 "multiply box by point (scale)" )
+insert ( 807 2617 0 "divide box by point (scale)" )
+insert ( 808 2617 0 "horizontally aligned" )
+insert ( 809 2617 0 "vertically aligned" )
+insert ( 843 2617 0 multiply )
+insert ( 844 2617 0 divide )
+insert ( 845 2617 0 multiply )
+insert ( 900 2617 0 equal )
+insert ( 901 2617 0 "not equal" )
+insert ( 902 2617 0 "less than" )
+insert ( 903 2617 0 "greater than" )
+insert ( 904 2617 0 "less than or equal" )
+insert ( 905 2617 0 "greater than or equal" )
+insert ( 906 2617 0 add )
+insert ( 907 2617 0 subtract )
+insert ( 908 2617 0 multiply )
+insert ( 909 2617 0 divide )
+insert ( 3346 2617 0 multiply )
+insert ( 3347 2617 0 divide )
+insert ( 912 2617 0 multiply )
+insert ( 913 2617 0 divide )
+insert ( 914 2617 0 multiply )
+insert ( 915 2617 0 divide )
+insert ( 916 2617 0 multiply )
+insert ( 3349 2617 0 multiply )
+insert ( 917 2617 0 multiply )
+insert ( 918 2617 0 multiply )
+insert ( 3825 2617 0 divide )
+insert ( 965 2617 0 exponentiation )
+insert ( 966 2617 0 "add/update ACL item" )
+insert ( 967 2617 0 "remove ACL item" )
+insert ( 968 2617 0 contains )
+insert ( 974 2617 0 equal )
+insert ( 969 2617 0 "center of" )
+insert ( 970 2617 0 "center of" )
+insert ( 971 2617 0 "center of" )
+insert ( 1054 2617 0 equal )
+insert ( 1055 2617 0 "matches regular expression, case-sensitive" )
+insert ( 1056 2617 0 "does not match regular expression, case-sensitive" )
+insert ( 1057 2617 0 "not equal" )
+insert ( 1058 2617 0 "less than" )
+insert ( 1059 2617 0 "less than or equal" )
+insert ( 1060 2617 0 "greater than" )
+insert ( 1061 2617 0 "greater than or equal" )
+insert ( 1070 2617 0 equal )
+insert ( 1071 2617 0 "not equal" )
+insert ( 1072 2617 0 "less than" )
+insert ( 1073 2617 0 "greater than" )
+insert ( 1074 2617 0 "less than or equal" )
+insert ( 1075 2617 0 "greater than or equal" )
+insert ( 1076 2617 0 add )
+insert ( 1077 2617 0 subtract )
+insert ( 1093 2617 0 equal )
+insert ( 1094 2617 0 "not equal" )
+insert ( 1095 2617 0 "less than" )
+insert ( 1096 2617 0 "less than or equal" )
+insert ( 1097 2617 0 "greater than" )
+insert ( 1098 2617 0 "greater than or equal" )
+insert ( 1099 2617 0 subtract )
+insert ( 1100 2617 0 add )
+insert ( 1101 2617 0 subtract )
+insert ( 1108 2617 0 equal )
+insert ( 1109 2617 0 "not equal" )
+insert ( 1110 2617 0 "less than" )
+insert ( 1111 2617 0 "less than or equal" )
+insert ( 1112 2617 0 "greater than" )
+insert ( 1113 2617 0 "greater than or equal" )
+insert ( 1550 2617 0 equal )
+insert ( 1551 2617 0 "not equal" )
+insert ( 1552 2617 0 "less than" )
+insert ( 1553 2617 0 "less than or equal" )
+insert ( 1554 2617 0 "greater than" )
+insert ( 1555 2617 0 "greater than or equal" )
+insert ( 1116 2617 0 add )
+insert ( 1117 2617 0 subtract )
+insert ( 1118 2617 0 divide )
+insert ( 1119 2617 0 multiply )
+insert ( 1120 2617 0 equal )
+insert ( 1121 2617 0 "not equal" )
+insert ( 1122 2617 0 "less than" )
+insert ( 1123 2617 0 "greater than" )
+insert ( 1124 2617 0 "less than or equal" )
+insert ( 1125 2617 0 "greater than or equal" )
+insert ( 1126 2617 0 add )
+insert ( 1127 2617 0 subtract )
+insert ( 1128 2617 0 divide )
+insert ( 1129 2617 0 multiply )
+insert ( 1130 2617 0 equal )
+insert ( 1131 2617 0 "not equal" )
+insert ( 1132 2617 0 "less than" )
+insert ( 1133 2617 0 "greater than" )
+insert ( 1134 2617 0 "less than or equal" )
+insert ( 1135 2617 0 "greater than or equal" )
+insert ( 1207 2617 0 "matches LIKE expression" )
+insert ( 1208 2617 0 "does not match LIKE expression" )
+insert ( 1209 2617 0 "matches LIKE expression" )
+insert ( 1210 2617 0 "does not match LIKE expression" )
+insert ( 1211 2617 0 "matches LIKE expression" )
+insert ( 1212 2617 0 "does not match LIKE expression" )
+insert ( 1226 2617 0 "matches regular expression, case-insensitive" )
+insert ( 1227 2617 0 "does not match regular expression, case-insensitive" )
+insert ( 1228 2617 0 "matches regular expression, case-insensitive" )
+insert ( 1229 2617 0 "does not match regular expression, case-insensitive" )
+insert ( 1234 2617 0 "matches regular expression, case-insensitive" )
+insert ( 1235 2617 0 "does not match regular expression, case-insensitive" )
+insert ( 1320 2617 0 equal )
+insert ( 1321 2617 0 "not equal" )
+insert ( 1322 2617 0 "less than" )
+insert ( 1323 2617 0 "less than or equal" )
+insert ( 1324 2617 0 "greater than" )
+insert ( 1325 2617 0 "greater than or equal" )
+insert ( 1327 2617 0 add )
+insert ( 1328 2617 0 subtract )
+insert ( 1329 2617 0 subtract )
+insert ( 1330 2617 0 equal )
+insert ( 1331 2617 0 "not equal" )
+insert ( 1332 2617 0 "less than" )
+insert ( 1333 2617 0 "less than or equal" )
+insert ( 1334 2617 0 "greater than" )
+insert ( 1335 2617 0 "greater than or equal" )
+insert ( 1336 2617 0 negate )
+insert ( 1337 2617 0 add )
+insert ( 1338 2617 0 subtract )
+insert ( 1360 2617 0 "convert date and time to timestamp" )
+insert ( 1361 2617 0 "convert date and time with time zone to timestamp with time zone" )
+insert ( 1363 2617 0 "convert time and date to timestamp" )
+insert ( 1366 2617 0 "convert time with time zone and date to timestamp with time zone" )
+insert ( 1399 2617 0 subtract )
+insert ( 1420 2617 0 "center of" )
+insert ( 1500 2617 0 "equal by area" )
+insert ( 1501 2617 0 "not equal by area" )
+insert ( 1502 2617 0 "less than by area" )
+insert ( 1503 2617 0 "greater than by area" )
+insert ( 1504 2617 0 "less than or equal by area" )
+insert ( 1505 2617 0 "greater than or equal by area" )
+insert ( 1506 2617 0 "is left of" )
+insert ( 1507 2617 0 "overlaps or is left of" )
+insert ( 1508 2617 0 "overlaps or is right of" )
+insert ( 1509 2617 0 "is right of" )
+insert ( 1510 2617 0 "is contained by" )
+insert ( 1511 2617 0 contains )
+insert ( 1512 2617 0 "same as" )
+insert ( 1513 2617 0 overlaps )
+insert ( 1514 2617 0 "is above" )
+insert ( 1515 2617 0 "is below" )
+insert ( 1516 2617 0 add )
+insert ( 1517 2617 0 subtract )
+insert ( 1518 2617 0 multiply )
+insert ( 1519 2617 0 divide )
+insert ( 1520 2617 0 "distance between" )
+insert ( 1521 2617 0 "number of points" )
+insert ( 1522 2617 0 "distance between" )
+insert ( 3291 2617 0 "distance between" )
+insert ( 3276 2617 0 "distance between" )
+insert ( 3289 2617 0 "distance between" )
+insert ( 1523 2617 0 "distance between" )
+insert ( 1383 2617 0 "distance between" )
+insert ( 1524 2617 0 "distance between" )
+insert ( 1382 2617 0 "distance between" )
+insert ( 1525 2617 0 intersect )
+insert ( 1526 2617 0 parallel )
+insert ( 1527 2617 0 perpendicular )
+insert ( 1528 2617 0 horizontal )
+insert ( 1529 2617 0 vertical )
+insert ( 1535 2617 0 equal )
+insert ( 1536 2617 0 "intersection point" )
+insert ( 1537 2617 0 intersect )
+insert ( 1538 2617 0 intersect )
+insert ( 1539 2617 0 intersect )
+insert ( 1546 2617 0 "point on line" )
+insert ( 1547 2617 0 "is contained by" )
+insert ( 1548 2617 0 "lseg on line" )
+insert ( 1549 2617 0 "is contained by" )
+insert ( 1557 2617 0 "closest point to A on B" )
+insert ( 1558 2617 0 "closest point to A on B" )
+insert ( 1559 2617 0 "closest point to A on B" )
+insert ( 1566 2617 0 "closest point to A on B" )
+insert ( 1567 2617 0 "closest point to A on B" )
+insert ( 1568 2617 0 "closest point to A on B" )
+insert ( 1577 2617 0 "closest point to A on B" )
+insert ( 1578 2617 0 "closest point to A on B" )
+insert ( 1583 2617 0 multiply )
+insert ( 1584 2617 0 multiply )
+insert ( 1585 2617 0 divide )
+insert ( 1586 2617 0 "not equal" )
+insert ( 1587 2617 0 "less than by length" )
+insert ( 1588 2617 0 "less than or equal by length" )
+insert ( 1589 2617 0 "greater than by length" )
+insert ( 1590 2617 0 "greater than or equal by length" )
+insert ( 1591 2617 0 "distance between endpoints" )
+insert ( 1611 2617 0 intersect )
+insert ( 1612 2617 0 parallel )
+insert ( 1613 2617 0 perpendicular )
+insert ( 1614 2617 0 horizontal )
+insert ( 1615 2617 0 vertical )
+insert ( 1616 2617 0 equal )
+insert ( 1617 2617 0 "intersection point" )
+insert ( 1220 2617 0 equal )
+insert ( 1221 2617 0 "not equal" )
+insert ( 1222 2617 0 "less than" )
+insert ( 1223 2617 0 "less than or equal" )
+insert ( 1224 2617 0 "greater than" )
+insert ( 1225 2617 0 "greater than or equal" )
+insert ( 3147 2617 0 "bitwise not" )
+insert ( 3148 2617 0 "bitwise and" )
+insert ( 3149 2617 0 "bitwise or" )
+insert ( 3362 2617 0 equal )
+insert ( 3363 2617 0 "not equal" )
+insert ( 3364 2617 0 "less than" )
+insert ( 3365 2617 0 "less than or equal" )
+insert ( 3366 2617 0 "greater than" )
+insert ( 3367 2617 0 "greater than or equal" )
+insert ( 3368 2617 0 "bitwise not" )
+insert ( 3369 2617 0 "bitwise and" )
+insert ( 3370 2617 0 "bitwise or" )
+insert ( 1201 2617 0 equal )
+insert ( 1202 2617 0 "not equal" )
+insert ( 1203 2617 0 "less than" )
+insert ( 1204 2617 0 "less than or equal" )
+insert ( 1205 2617 0 "greater than" )
+insert ( 1206 2617 0 "greater than or equal" )
+insert ( 931 2617 0 "is subnet" )
+insert ( 932 2617 0 "is subnet or equal" )
+insert ( 933 2617 0 "is supernet" )
+insert ( 934 2617 0 "is supernet or equal" )
+insert ( 3552 2617 0 "overlaps (is subnet or supernet)" )
+insert ( 2634 2617 0 "bitwise not" )
+insert ( 2635 2617 0 "bitwise and" )
+insert ( 2636 2617 0 "bitwise or" )
+insert ( 2637 2617 0 add )
+insert ( 2638 2617 0 add )
+insert ( 2639 2617 0 subtract )
+insert ( 2640 2617 0 subtract )
+insert ( 1625 2617 0 "matches LIKE expression, case-insensitive" )
+insert ( 1626 2617 0 "does not match LIKE expression, case-insensitive" )
+insert ( 1627 2617 0 "matches LIKE expression, case-insensitive" )
+insert ( 1628 2617 0 "does not match LIKE expression, case-insensitive" )
+insert ( 1629 2617 0 "matches LIKE expression, case-insensitive" )
+insert ( 1630 2617 0 "does not match LIKE expression, case-insensitive" )
+insert ( 1751 2617 0 negate )
+insert ( 1752 2617 0 equal )
+insert ( 1753 2617 0 "not equal" )
+insert ( 1754 2617 0 "less than" )
+insert ( 1755 2617 0 "less than or equal" )
+insert ( 1756 2617 0 "greater than" )
+insert ( 1757 2617 0 "greater than or equal" )
+insert ( 1758 2617 0 add )
+insert ( 1759 2617 0 subtract )
+insert ( 1760 2617 0 multiply )
+insert ( 1761 2617 0 divide )
+insert ( 1762 2617 0 modulus )
+insert ( 1038 2617 0 exponentiation )
+insert ( 1763 2617 0 "absolute value" )
+insert ( 1784 2617 0 equal )
+insert ( 1785 2617 0 "not equal" )
+insert ( 1786 2617 0 "less than" )
+insert ( 1787 2617 0 "greater than" )
+insert ( 1788 2617 0 "less than or equal" )
+insert ( 1789 2617 0 "greater than or equal" )
+insert ( 1791 2617 0 "bitwise and" )
+insert ( 1792 2617 0 "bitwise or" )
+insert ( 1793 2617 0 "bitwise exclusive or" )
+insert ( 1794 2617 0 "bitwise not" )
+insert ( 1795 2617 0 "bitwise shift left" )
+insert ( 1796 2617 0 "bitwise shift right" )
+insert ( 1797 2617 0 concatenate )
+insert ( 1800 2617 0 add )
+insert ( 1801 2617 0 subtract )
+insert ( 1802 2617 0 add )
+insert ( 1803 2617 0 subtract )
+insert ( 1804 2617 0 equal )
+insert ( 1805 2617 0 "not equal" )
+insert ( 1806 2617 0 "less than" )
+insert ( 1807 2617 0 "greater than" )
+insert ( 1808 2617 0 "less than or equal" )
+insert ( 1809 2617 0 "greater than or equal" )
+insert ( 1849 2617 0 add )
+insert ( 1862 2617 0 equal )
+insert ( 1863 2617 0 "not equal" )
+insert ( 1864 2617 0 "less than" )
+insert ( 1865 2617 0 "greater than" )
+insert ( 1866 2617 0 "less than or equal" )
+insert ( 1867 2617 0 "greater than or equal" )
+insert ( 1868 2617 0 equal )
+insert ( 1869 2617 0 "not equal" )
+insert ( 1870 2617 0 "less than" )
+insert ( 1871 2617 0 "greater than" )
+insert ( 1872 2617 0 "less than or equal" )
+insert ( 1873 2617 0 "greater than or equal" )
+insert ( 1874 2617 0 "bitwise and" )
+insert ( 1875 2617 0 "bitwise or" )
+insert ( 1876 2617 0 "bitwise exclusive or" )
+insert ( 1877 2617 0 "bitwise not" )
+insert ( 1878 2617 0 "bitwise shift left" )
+insert ( 1879 2617 0 "bitwise shift right" )
+insert ( 1880 2617 0 "bitwise and" )
+insert ( 1881 2617 0 "bitwise or" )
+insert ( 1882 2617 0 "bitwise exclusive or" )
+insert ( 1883 2617 0 "bitwise not" )
+insert ( 1884 2617 0 "bitwise shift left" )
+insert ( 1885 2617 0 "bitwise shift right" )
+insert ( 1886 2617 0 "bitwise and" )
+insert ( 1887 2617 0 "bitwise or" )
+insert ( 1888 2617 0 "bitwise exclusive or" )
+insert ( 1889 2617 0 "bitwise not" )
+insert ( 1890 2617 0 "bitwise shift left" )
+insert ( 1891 2617 0 "bitwise shift right" )
+insert ( 1916 2617 0 "unary plus" )
+insert ( 1917 2617 0 "unary plus" )
+insert ( 1918 2617 0 "unary plus" )
+insert ( 1919 2617 0 "unary plus" )
+insert ( 1920 2617 0 "unary plus" )
+insert ( 1921 2617 0 "unary plus" )
+insert ( 1955 2617 0 equal )
+insert ( 1956 2617 0 "not equal" )
+insert ( 1957 2617 0 "less than" )
+insert ( 1958 2617 0 "less than or equal" )
+insert ( 1959 2617 0 "greater than" )
+insert ( 1960 2617 0 "greater than or equal" )
+insert ( 2016 2617 0 "matches LIKE expression" )
+insert ( 2017 2617 0 "does not match LIKE expression" )
+insert ( 2018 2617 0 concatenate )
+insert ( 2060 2617 0 equal )
+insert ( 2061 2617 0 "not equal" )
+insert ( 2062 2617 0 "less than" )
+insert ( 2063 2617 0 "less than or equal" )
+insert ( 2064 2617 0 "greater than" )
+insert ( 2065 2617 0 "greater than or equal" )
+insert ( 2066 2617 0 add )
+insert ( 2067 2617 0 subtract )
+insert ( 2068 2617 0 subtract )
+insert ( 2314 2617 0 "less than" )
+insert ( 2315 2617 0 "less than or equal" )
+insert ( 2317 2617 0 "greater than or equal" )
+insert ( 2318 2617 0 "greater than" )
+insert ( 2326 2617 0 "less than" )
+insert ( 2327 2617 0 "less than or equal" )
+insert ( 2329 2617 0 "greater than or equal" )
+insert ( 2330 2617 0 "greater than" )
+insert ( 2345 2617 0 "less than" )
+insert ( 2346 2617 0 "less than or equal" )
+insert ( 2347 2617 0 equal )
+insert ( 2348 2617 0 "greater than or equal" )
+insert ( 2349 2617 0 "greater than" )
+insert ( 2350 2617 0 "not equal" )
+insert ( 2358 2617 0 "less than" )
+insert ( 2359 2617 0 "less than or equal" )
+insert ( 2360 2617 0 equal )
+insert ( 2361 2617 0 "greater than or equal" )
+insert ( 2362 2617 0 "greater than" )
+insert ( 2363 2617 0 "not equal" )
+insert ( 2371 2617 0 "less than" )
+insert ( 2372 2617 0 "less than or equal" )
+insert ( 2373 2617 0 equal )
+insert ( 2374 2617 0 "greater than or equal" )
+insert ( 2375 2617 0 "greater than" )
+insert ( 2376 2617 0 "not equal" )
+insert ( 2384 2617 0 "less than" )
+insert ( 2385 2617 0 "less than or equal" )
+insert ( 2386 2617 0 equal )
+insert ( 2387 2617 0 "greater than or equal" )
+insert ( 2388 2617 0 "greater than" )
+insert ( 2389 2617 0 "not equal" )
+insert ( 2534 2617 0 "less than" )
+insert ( 2535 2617 0 "less than or equal" )
+insert ( 2536 2617 0 equal )
+insert ( 2537 2617 0 "greater than or equal" )
+insert ( 2538 2617 0 "greater than" )
+insert ( 2539 2617 0 "not equal" )
+insert ( 2540 2617 0 "less than" )
+insert ( 2541 2617 0 "less than or equal" )
+insert ( 2542 2617 0 equal )
+insert ( 2543 2617 0 "greater than or equal" )
+insert ( 2544 2617 0 "greater than" )
+insert ( 2545 2617 0 "not equal" )
+insert ( 2551 2617 0 add )
+insert ( 2552 2617 0 add )
+insert ( 2553 2617 0 add )
+insert ( 2554 2617 0 add )
+insert ( 2555 2617 0 add )
+insert ( 2570 2617 0 "is below" )
+insert ( 2571 2617 0 "overlaps or is below" )
+insert ( 2572 2617 0 "overlaps or is above" )
+insert ( 2573 2617 0 "is above" )
+insert ( 2574 2617 0 "is below" )
+insert ( 2575 2617 0 "overlaps or is below" )
+insert ( 2576 2617 0 "overlaps or is above" )
+insert ( 2577 2617 0 "is above" )
+insert ( 2589 2617 0 "overlaps or is below" )
+insert ( 2590 2617 0 "overlaps or is above" )
+insert ( 2750 2617 0 overlaps )
+insert ( 2751 2617 0 contains )
+insert ( 2752 2617 0 "is contained by" )
+insert ( 2779 2617 0 concatenate )
+insert ( 2780 2617 0 concatenate )
+insert ( 2860 2617 0 "deprecated, use <@ instead" )
+insert ( 2861 2617 0 "deprecated, use @> instead" )
+insert ( 2862 2617 0 "deprecated, use <@ instead" )
+insert ( 2863 2617 0 "deprecated, use @> instead" )
+insert ( 2864 2617 0 "deprecated, use <@ instead" )
+insert ( 2865 2617 0 "deprecated, use @> instead" )
+insert ( 2866 2617 0 "deprecated, use <@ instead" )
+insert ( 2867 2617 0 "deprecated, use <@ instead" )
+insert ( 2868 2617 0 "deprecated, use @> instead" )
+insert ( 2869 2617 0 "deprecated, use <@ instead" )
+insert ( 2870 2617 0 "deprecated, use @> instead" )
+insert ( 2871 2617 0 "deprecated, use <@ instead" )
+insert ( 2872 2617 0 "deprecated, use @> instead" )
+insert ( 2873 2617 0 "deprecated, use <@ instead" )
+insert ( 2874 2617 0 "deprecated, use <@ instead" )
+insert ( 2875 2617 0 "deprecated, use <@ instead" )
+insert ( 2876 2617 0 "deprecated, use <@ instead" )
+insert ( 2877 2617 0 "deprecated, use @> instead" )
+insert ( 2972 2617 0 equal )
+insert ( 2973 2617 0 "not equal" )
+insert ( 2974 2617 0 "less than" )
+insert ( 2975 2617 0 "greater than" )
+insert ( 2976 2617 0 "less than or equal" )
+insert ( 2977 2617 0 "greater than or equal" )
+insert ( 3222 2617 0 equal )
+insert ( 3223 2617 0 "not equal" )
+insert ( 3224 2617 0 "less than" )
+insert ( 3225 2617 0 "greater than" )
+insert ( 3226 2617 0 "less than or equal" )
+insert ( 3227 2617 0 "greater than or equal" )
+insert ( 3228 2617 0 minus )
+insert ( 3516 2617 0 equal )
+insert ( 3517 2617 0 "not equal" )
+insert ( 3518 2617 0 "less than" )
+insert ( 3519 2617 0 "greater than" )
+insert ( 3520 2617 0 "less than or equal" )
+insert ( 3521 2617 0 "greater than or equal" )
+insert ( 3627 2617 0 "less than" )
+insert ( 3628 2617 0 "less than or equal" )
+insert ( 3629 2617 0 equal )
+insert ( 3630 2617 0 "not equal" )
+insert ( 3631 2617 0 "greater than or equal" )
+insert ( 3632 2617 0 "greater than" )
+insert ( 3633 2617 0 concatenate )
+insert ( 3636 2617 0 "text search match" )
+insert ( 3637 2617 0 "text search match" )
+insert ( 3660 2617 0 "deprecated, use @@ instead" )
+insert ( 3661 2617 0 "deprecated, use @@ instead" )
+insert ( 3674 2617 0 "less than" )
+insert ( 3675 2617 0 "less than or equal" )
+insert ( 3676 2617 0 equal )
+insert ( 3677 2617 0 "not equal" )
+insert ( 3678 2617 0 "greater than or equal" )
+insert ( 3679 2617 0 "greater than" )
+insert ( 3680 2617 0 AND-concatenate )
+insert ( 3681 2617 0 OR-concatenate )
+insert ( 5005 2617 0 phrase-concatenate )
+insert ( 3682 2617 0 "NOT tsquery" )
+insert ( 3693 2617 0 contains )
+insert ( 3694 2617 0 "is contained by" )
+insert ( 3762 2617 0 "text search match" )
+insert ( 3763 2617 0 "text search match" )
+insert ( 2988 2617 0 equal )
+insert ( 2989 2617 0 "not equal" )
+insert ( 2990 2617 0 "less than" )
+insert ( 2991 2617 0 "greater than" )
+insert ( 2992 2617 0 "less than or equal" )
+insert ( 2993 2617 0 "greater than or equal" )
+insert ( 3188 2617 0 identical )
+insert ( 3189 2617 0 "not identical" )
+insert ( 3190 2617 0 "less than" )
+insert ( 3191 2617 0 "greater than" )
+insert ( 3192 2617 0 "less than or equal" )
+insert ( 3193 2617 0 "greater than or equal" )
+insert ( 3882 2617 0 equal )
+insert ( 3883 2617 0 "not equal" )
+insert ( 3884 2617 0 "less than" )
+insert ( 3885 2617 0 "less than or equal" )
+insert ( 3886 2617 0 "greater than or equal" )
+insert ( 3887 2617 0 "greater than" )
+insert ( 3888 2617 0 overlaps )
+insert ( 3889 2617 0 contains )
+insert ( 3890 2617 0 contains )
+insert ( 3891 2617 0 "is contained by" )
+insert ( 3892 2617 0 "is contained by" )
+insert ( 3893 2617 0 "is left of" )
+insert ( 3894 2617 0 "is right of" )
+insert ( 3895 2617 0 "overlaps or is left of" )
+insert ( 3896 2617 0 "overlaps or is right of" )
+insert ( 3897 2617 0 "is adjacent to" )
+insert ( 3898 2617 0 "range union" )
+insert ( 3899 2617 0 "range difference" )
+insert ( 3900 2617 0 "range intersection" )
+insert ( 3962 2617 0 "get json object field" )
+insert ( 3963 2617 0 "get json object field as text" )
+insert ( 3964 2617 0 "get json array element" )
+insert ( 3965 2617 0 "get json array element as text" )
+insert ( 3966 2617 0 "get value from json with path elements" )
+insert ( 3967 2617 0 "get value from json as text with path elements" )
+insert ( 3211 2617 0 "get jsonb object field" )
+insert ( 3477 2617 0 "get jsonb object field as text" )
+insert ( 3212 2617 0 "get jsonb array element" )
+insert ( 3481 2617 0 "get jsonb array element as text" )
+insert ( 3213 2617 0 "get value from jsonb with path elements" )
+insert ( 3206 2617 0 "get value from jsonb as text with path elements" )
+insert ( 3240 2617 0 equal )
+insert ( 3241 2617 0 "not equal" )
+insert ( 3242 2617 0 "less than" )
+insert ( 3243 2617 0 "greater than" )
+insert ( 3244 2617 0 "less than or equal" )
+insert ( 3245 2617 0 "greater than or equal" )
+insert ( 3246 2617 0 contains )
+insert ( 3247 2617 0 "key exists" )
+insert ( 3248 2617 0 "any key exists" )
+insert ( 3249 2617 0 "all keys exist" )
+insert ( 3250 2617 0 "is contained by" )
+insert ( 3284 2617 0 concatenate )
+insert ( 3285 2617 0 "delete object field" )
+insert ( 3398 2617 0 "delete object fields" )
+insert ( 3286 2617 0 "delete array element" )
+insert ( 3287 2617 0 "delete path" )
+insert ( 4012 2617 0 "jsonpath exists" )
+insert ( 4013 2617 0 "jsonpath match" )
+insert ( 2 2601 0 "heap table access method" )
+insert ( 403 2601 0 "b-tree index access method" )
+insert ( 405 2601 0 "hash index access method" )
+insert ( 783 2601 0 "GiST index access method" )
+insert ( 2742 2601 0 "GIN index access method" )
+insert ( 4000 2601 0 "SP-GiST index access method" )
+insert ( 3580 2601 0 "block range index (BRIN) access method" )
+insert ( 12 2612 0 "built-in functions" )
+insert ( 13 2612 0 "dynamically-loaded C functions" )
+insert ( 14 2612 0 "SQL-language functions" )
+insert ( 11 2615 0 "system catalog schema" )
+insert ( 99 2615 0 "reserved schema for TOAST tables" )
+insert ( 2200 2615 0 "standard public schema" )
+insert ( 4402 2607 0 "conversion for KOI8R to MULE_INTERNAL" )
+insert ( 4403 2607 0 "conversion for MULE_INTERNAL to KOI8R" )
+insert ( 4404 2607 0 "conversion for ISO-8859-5 to MULE_INTERNAL" )
+insert ( 4405 2607 0 "conversion for MULE_INTERNAL to ISO-8859-5" )
+insert ( 4406 2607 0 "conversion for WIN1251 to MULE_INTERNAL" )
+insert ( 4407 2607 0 "conversion for MULE_INTERNAL to WIN1251" )
+insert ( 4408 2607 0 "conversion for WIN866 to MULE_INTERNAL" )
+insert ( 4409 2607 0 "conversion for MULE_INTERNAL to WIN866" )
+insert ( 4410 2607 0 "conversion for KOI8R to WIN1251" )
+insert ( 4411 2607 0 "conversion for WIN1251 to KOI8R" )
+insert ( 4412 2607 0 "conversion for KOI8R to WIN866" )
+insert ( 4413 2607 0 "conversion for WIN866 to KOI8R" )
+insert ( 4414 2607 0 "conversion for WIN866 to WIN1251" )
+insert ( 4415 2607 0 "conversion for WIN1251 to WIN866" )
+insert ( 4416 2607 0 "conversion for ISO-8859-5 to KOI8R" )
+insert ( 4417 2607 0 "conversion for KOI8R to ISO-8859-5" )
+insert ( 4418 2607 0 "conversion for ISO-8859-5 to WIN1251" )
+insert ( 4419 2607 0 "conversion for WIN1251 to ISO-8859-5" )
+insert ( 4420 2607 0 "conversion for ISO-8859-5 to WIN866" )
+insert ( 4421 2607 0 "conversion for WIN866 to ISO-8859-5" )
+insert ( 4422 2607 0 "conversion for EUC_CN to MULE_INTERNAL" )
+insert ( 4423 2607 0 "conversion for MULE_INTERNAL to EUC_CN" )
+insert ( 4424 2607 0 "conversion for EUC_JP to SJIS" )
+insert ( 4425 2607 0 "conversion for SJIS to EUC_JP" )
+insert ( 4426 2607 0 "conversion for EUC_JP to MULE_INTERNAL" )
+insert ( 4427 2607 0 "conversion for SJIS to MULE_INTERNAL" )
+insert ( 4428 2607 0 "conversion for MULE_INTERNAL to EUC_JP" )
+insert ( 4429 2607 0 "conversion for MULE_INTERNAL to SJIS" )
+insert ( 4430 2607 0 "conversion for EUC_KR to MULE_INTERNAL" )
+insert ( 4431 2607 0 "conversion for MULE_INTERNAL to EUC_KR" )
+insert ( 4432 2607 0 "conversion for EUC_TW to BIG5" )
+insert ( 4433 2607 0 "conversion for BIG5 to EUC_TW" )
+insert ( 4434 2607 0 "conversion for EUC_TW to MULE_INTERNAL" )
+insert ( 4435 2607 0 "conversion for BIG5 to MULE_INTERNAL" )
+insert ( 4436 2607 0 "conversion for MULE_INTERNAL to EUC_TW" )
+insert ( 4437 2607 0 "conversion for MULE_INTERNAL to BIG5" )
+insert ( 4438 2607 0 "conversion for LATIN2 to MULE_INTERNAL" )
+insert ( 4439 2607 0 "conversion for MULE_INTERNAL to LATIN2" )
+insert ( 4440 2607 0 "conversion for WIN1250 to MULE_INTERNAL" )
+insert ( 4441 2607 0 "conversion for MULE_INTERNAL to WIN1250" )
+insert ( 4442 2607 0 "conversion for LATIN2 to WIN1250" )
+insert ( 4443 2607 0 "conversion for WIN1250 to LATIN2" )
+insert ( 4444 2607 0 "conversion for LATIN1 to MULE_INTERNAL" )
+insert ( 4445 2607 0 "conversion for MULE_INTERNAL to LATIN1" )
+insert ( 4446 2607 0 "conversion for LATIN3 to MULE_INTERNAL" )
+insert ( 4447 2607 0 "conversion for MULE_INTERNAL to LATIN3" )
+insert ( 4448 2607 0 "conversion for LATIN4 to MULE_INTERNAL" )
+insert ( 4449 2607 0 "conversion for MULE_INTERNAL to LATIN4" )
+insert ( 4452 2607 0 "conversion for BIG5 to UTF8" )
+insert ( 4453 2607 0 "conversion for UTF8 to BIG5" )
+insert ( 4454 2607 0 "conversion for UTF8 to KOI8R" )
+insert ( 4455 2607 0 "conversion for KOI8R to UTF8" )
+insert ( 4456 2607 0 "conversion for UTF8 to KOI8U" )
+insert ( 4457 2607 0 "conversion for KOI8U to UTF8" )
+insert ( 4458 2607 0 "conversion for UTF8 to WIN866" )
+insert ( 4459 2607 0 "conversion for WIN866 to UTF8" )
+insert ( 4460 2607 0 "conversion for UTF8 to WIN874" )
+insert ( 4461 2607 0 "conversion for WIN874 to UTF8" )
+insert ( 4462 2607 0 "conversion for UTF8 to WIN1250" )
+insert ( 4463 2607 0 "conversion for WIN1250 to UTF8" )
+insert ( 4464 2607 0 "conversion for UTF8 to WIN1251" )
+insert ( 4465 2607 0 "conversion for WIN1251 to UTF8" )
+insert ( 4466 2607 0 "conversion for UTF8 to WIN1252" )
+insert ( 4467 2607 0 "conversion for WIN1252 to UTF8" )
+insert ( 4468 2607 0 "conversion for UTF8 to WIN1253" )
+insert ( 4469 2607 0 "conversion for WIN1253 to UTF8" )
+insert ( 4470 2607 0 "conversion for UTF8 to WIN1254" )
+insert ( 4471 2607 0 "conversion for WIN1254 to UTF8" )
+insert ( 4472 2607 0 "conversion for UTF8 to WIN1255" )
+insert ( 4473 2607 0 "conversion for WIN1255 to UTF8" )
+insert ( 4474 2607 0 "conversion for UTF8 to WIN1256" )
+insert ( 4475 2607 0 "conversion for WIN1256 to UTF8" )
+insert ( 4476 2607 0 "conversion for UTF8 to WIN1257" )
+insert ( 4477 2607 0 "conversion for WIN1257 to UTF8" )
+insert ( 4478 2607 0 "conversion for UTF8 to WIN1258" )
+insert ( 4479 2607 0 "conversion for WIN1258 to UTF8" )
+insert ( 4480 2607 0 "conversion for EUC_CN to UTF8" )
+insert ( 4481 2607 0 "conversion for UTF8 to EUC_CN" )
+insert ( 4482 2607 0 "conversion for EUC_JP to UTF8" )
+insert ( 4483 2607 0 "conversion for UTF8 to EUC_JP" )
+insert ( 4484 2607 0 "conversion for EUC_KR to UTF8" )
+insert ( 4485 2607 0 "conversion for UTF8 to EUC_KR" )
+insert ( 4486 2607 0 "conversion for EUC_TW to UTF8" )
+insert ( 4487 2607 0 "conversion for UTF8 to EUC_TW" )
+insert ( 4488 2607 0 "conversion for GB18030 to UTF8" )
+insert ( 4489 2607 0 "conversion for UTF8 to GB18030" )
+insert ( 4490 2607 0 "conversion for GBK to UTF8" )
+insert ( 4491 2607 0 "conversion for UTF8 to GBK" )
+insert ( 4492 2607 0 "conversion for UTF8 to LATIN2" )
+insert ( 4493 2607 0 "conversion for LATIN2 to UTF8" )
+insert ( 4494 2607 0 "conversion for UTF8 to LATIN3" )
+insert ( 4495 2607 0 "conversion for LATIN3 to UTF8" )
+insert ( 4496 2607 0 "conversion for UTF8 to LATIN4" )
+insert ( 4497 2607 0 "conversion for LATIN4 to UTF8" )
+insert ( 4498 2607 0 "conversion for UTF8 to LATIN5" )
+insert ( 4499 2607 0 "conversion for LATIN5 to UTF8" )
+insert ( 4500 2607 0 "conversion for UTF8 to LATIN6" )
+insert ( 4501 2607 0 "conversion for LATIN6 to UTF8" )
+insert ( 4502 2607 0 "conversion for UTF8 to LATIN7" )
+insert ( 4503 2607 0 "conversion for LATIN7 to UTF8" )
+insert ( 4504 2607 0 "conversion for UTF8 to LATIN8" )
+insert ( 4505 2607 0 "conversion for LATIN8 to UTF8" )
+insert ( 4506 2607 0 "conversion for UTF8 to LATIN9" )
+insert ( 4507 2607 0 "conversion for LATIN9 to UTF8" )
+insert ( 4508 2607 0 "conversion for UTF8 to LATIN10" )
+insert ( 4509 2607 0 "conversion for LATIN10 to UTF8" )
+insert ( 4510 2607 0 "conversion for UTF8 to ISO-8859-5" )
+insert ( 4511 2607 0 "conversion for ISO-8859-5 to UTF8" )
+insert ( 4512 2607 0 "conversion for UTF8 to ISO-8859-6" )
+insert ( 4513 2607 0 "conversion for ISO-8859-6 to UTF8" )
+insert ( 4514 2607 0 "conversion for UTF8 to ISO-8859-7" )
+insert ( 4515 2607 0 "conversion for ISO-8859-7 to UTF8" )
+insert ( 4516 2607 0 "conversion for UTF8 to ISO-8859-8" )
+insert ( 4517 2607 0 "conversion for ISO-8859-8 to UTF8" )
+insert ( 4518 2607 0 "conversion for LATIN1 to UTF8" )
+insert ( 4519 2607 0 "conversion for UTF8 to LATIN1" )
+insert ( 4520 2607 0 "conversion for JOHAB to UTF8" )
+insert ( 4521 2607 0 "conversion for UTF8 to JOHAB" )
+insert ( 4522 2607 0 "conversion for SJIS to UTF8" )
+insert ( 4523 2607 0 "conversion for UTF8 to SJIS" )
+insert ( 4524 2607 0 "conversion for UHC to UTF8" )
+insert ( 4525 2607 0 "conversion for UTF8 to UHC" )
+insert ( 4526 2607 0 "conversion for EUC_JIS_2004 to UTF8" )
+insert ( 4527 2607 0 "conversion for UTF8 to EUC_JIS_2004" )
+insert ( 4528 2607 0 "conversion for SHIFT_JIS_2004 to UTF8" )
+insert ( 4529 2607 0 "conversion for UTF8 to SHIFT_JIS_2004" )
+insert ( 4530 2607 0 "conversion for EUC_JIS_2004 to SHIFT_JIS_2004" )
+insert ( 4531 2607 0 "conversion for SHIFT_JIS_2004 to EUC_JIS_2004" )
+insert ( 3748 3602 0 "simple configuration" )
+insert ( 3765 3600 0 "simple dictionary: just lower case and check for stopword" )
+insert ( 3722 3601 0 "default word parser" )
+insert ( 3727 3764 0 "simple dictionary: just lower case and check for stopword" )
+insert ( 3730 3764 0 "synonym dictionary: replace word by its synonym" )
+insert ( 3733 3764 0 "ispell dictionary" )
+insert ( 3742 3764 0 "thesaurus dictionary: phrase by phrase substitution" )
+insert ( 100 3456 0 "database''s default collation" )
+insert ( 950 3456 0 "standard C collation" )
+insert ( 951 3456 0 "standard POSIX collation" )
+close pg_description
+create pg_cast 2605
+ (
+ oid = oid ,
+ castsource = oid ,
+ casttarget = oid ,
+ castfunc = oid ,
+ castcontext = char ,
+ castmethod = char
+ )
+open pg_cast
+insert ( 11323 20 21 714 a f )
+insert ( 11324 20 23 480 a f )
+insert ( 11325 20 700 652 i f )
+insert ( 11326 20 701 482 i f )
+insert ( 11327 20 1700 1781 i f )
+insert ( 11328 21 20 754 i f )
+insert ( 11329 21 23 313 i f )
+insert ( 11330 21 700 236 i f )
+insert ( 11331 21 701 235 i f )
+insert ( 11332 21 1700 1782 i f )
+insert ( 11333 23 20 481 i f )
+insert ( 11334 23 21 314 a f )
+insert ( 11335 23 700 318 i f )
+insert ( 11336 23 701 316 i f )
+insert ( 11337 23 1700 1740 i f )
+insert ( 11338 700 20 653 a f )
+insert ( 11339 700 21 238 a f )
+insert ( 11340 700 23 319 a f )
+insert ( 11341 700 701 311 i f )
+insert ( 11342 700 1700 1742 a f )
+insert ( 11343 701 20 483 a f )
+insert ( 11344 701 21 237 a f )
+insert ( 11345 701 23 317 a f )
+insert ( 11346 701 700 312 a f )
+insert ( 11347 701 1700 1743 a f )
+insert ( 11348 1700 20 1779 a f )
+insert ( 11349 1700 21 1783 a f )
+insert ( 11350 1700 23 1744 a f )
+insert ( 11351 1700 700 1745 i f )
+insert ( 11352 1700 701 1746 i f )
+insert ( 11353 790 1700 3823 a f )
+insert ( 11354 1700 790 3824 a f )
+insert ( 11355 23 790 3811 a f )
+insert ( 11356 20 790 3812 a f )
+insert ( 11357 23 16 2557 e f )
+insert ( 11358 16 23 2558 e f )
+insert ( 11359 5069 28 5071 e f )
+insert ( 11360 20 26 1287 i f )
+insert ( 11361 21 26 313 i f )
+insert ( 11362 23 26 0 i b )
+insert ( 11363 26 20 1288 a f )
+insert ( 11364 26 23 0 a b )
+insert ( 11365 26 24 0 i b )
+insert ( 11366 24 26 0 i b )
+insert ( 11367 20 24 1287 i f )
+insert ( 11368 21 24 313 i f )
+insert ( 11369 23 24 0 i b )
+insert ( 11370 24 20 1288 a f )
+insert ( 11371 24 23 0 a b )
+insert ( 11372 24 2202 0 i b )
+insert ( 11373 2202 24 0 i b )
+insert ( 11374 26 2202 0 i b )
+insert ( 11375 2202 26 0 i b )
+insert ( 11376 20 2202 1287 i f )
+insert ( 11377 21 2202 313 i f )
+insert ( 11378 23 2202 0 i b )
+insert ( 11379 2202 20 1288 a f )
+insert ( 11380 2202 23 0 a b )
+insert ( 11381 26 2203 0 i b )
+insert ( 11382 2203 26 0 i b )
+insert ( 11383 20 2203 1287 i f )
+insert ( 11384 21 2203 313 i f )
+insert ( 11385 23 2203 0 i b )
+insert ( 11386 2203 20 1288 a f )
+insert ( 11387 2203 23 0 a b )
+insert ( 11388 2203 2204 0 i b )
+insert ( 11389 2204 2203 0 i b )
+insert ( 11390 26 2204 0 i b )
+insert ( 11391 2204 26 0 i b )
+insert ( 11392 20 2204 1287 i f )
+insert ( 11393 21 2204 313 i f )
+insert ( 11394 23 2204 0 i b )
+insert ( 11395 2204 20 1288 a f )
+insert ( 11396 2204 23 0 a b )
+insert ( 11397 26 2205 0 i b )
+insert ( 11398 2205 26 0 i b )
+insert ( 11399 20 2205 1287 i f )
+insert ( 11400 21 2205 313 i f )
+insert ( 11401 23 2205 0 i b )
+insert ( 11402 2205 20 1288 a f )
+insert ( 11403 2205 23 0 a b )
+insert ( 11404 26 4191 0 i b )
+insert ( 11405 4191 26 0 i b )
+insert ( 11406 20 4191 1287 i f )
+insert ( 11407 21 4191 313 i f )
+insert ( 11408 23 4191 0 i b )
+insert ( 11409 4191 20 1288 a f )
+insert ( 11410 4191 23 0 a b )
+insert ( 11411 26 2206 0 i b )
+insert ( 11412 2206 26 0 i b )
+insert ( 11413 20 2206 1287 i f )
+insert ( 11414 21 2206 313 i f )
+insert ( 11415 23 2206 0 i b )
+insert ( 11416 2206 20 1288 a f )
+insert ( 11417 2206 23 0 a b )
+insert ( 11418 26 3734 0 i b )
+insert ( 11419 3734 26 0 i b )
+insert ( 11420 20 3734 1287 i f )
+insert ( 11421 21 3734 313 i f )
+insert ( 11422 23 3734 0 i b )
+insert ( 11423 3734 20 1288 a f )
+insert ( 11424 3734 23 0 a b )
+insert ( 11425 26 3769 0 i b )
+insert ( 11426 3769 26 0 i b )
+insert ( 11427 20 3769 1287 i f )
+insert ( 11428 21 3769 313 i f )
+insert ( 11429 23 3769 0 i b )
+insert ( 11430 3769 20 1288 a f )
+insert ( 11431 3769 23 0 a b )
+insert ( 11432 25 2205 1079 i f )
+insert ( 11433 1043 2205 1079 i f )
+insert ( 11434 26 4096 0 i b )
+insert ( 11435 4096 26 0 i b )
+insert ( 11436 20 4096 1287 i f )
+insert ( 11437 21 4096 313 i f )
+insert ( 11438 23 4096 0 i b )
+insert ( 11439 4096 20 1288 a f )
+insert ( 11440 4096 23 0 a b )
+insert ( 11441 26 4089 0 i b )
+insert ( 11442 4089 26 0 i b )
+insert ( 11443 20 4089 1287 i f )
+insert ( 11444 21 4089 313 i f )
+insert ( 11445 23 4089 0 i b )
+insert ( 11446 4089 20 1288 a f )
+insert ( 11447 4089 23 0 a b )
+insert ( 11448 25 1042 0 i b )
+insert ( 11449 25 1043 0 i b )
+insert ( 11450 1042 25 401 i f )
+insert ( 11451 1042 1043 401 i f )
+insert ( 11452 1043 25 0 i b )
+insert ( 11453 1043 1042 0 i b )
+insert ( 11454 18 25 946 i f )
+insert ( 11455 18 1042 860 a f )
+insert ( 11456 18 1043 946 a f )
+insert ( 11457 19 25 406 i f )
+insert ( 11458 19 1042 408 a f )
+insert ( 11459 19 1043 1401 a f )
+insert ( 11460 25 18 944 a f )
+insert ( 11461 1042 18 944 a f )
+insert ( 11462 1043 18 944 a f )
+insert ( 11463 25 19 407 i f )
+insert ( 11464 1042 19 409 i f )
+insert ( 11465 1043 19 1400 i f )
+insert ( 11466 18 23 77 e f )
+insert ( 11467 23 18 78 e f )
+insert ( 11468 194 25 0 i b )
+insert ( 11469 3361 17 0 i b )
+insert ( 11470 3361 25 0 i i )
+insert ( 11471 3402 17 0 i b )
+insert ( 11472 3402 25 0 i i )
+insert ( 11473 5017 17 0 i b )
+insert ( 11474 5017 25 0 i i )
+insert ( 11475 1082 1114 2024 i f )
+insert ( 11476 1082 1184 1174 i f )
+insert ( 11477 1083 1186 1370 i f )
+insert ( 11478 1083 1266 2047 i f )
+insert ( 11479 1114 1082 2029 a f )
+insert ( 11480 1114 1083 1316 a f )
+insert ( 11481 1114 1184 2028 i f )
+insert ( 11482 1184 1082 1178 a f )
+insert ( 11483 1184 1083 2019 a f )
+insert ( 11484 1184 1114 2027 a f )
+insert ( 11485 1184 1266 1388 a f )
+insert ( 11486 1186 1083 1419 a f )
+insert ( 11487 1266 1083 2046 a f )
+insert ( 11488 600 603 4091 a f )
+insert ( 11489 601 600 1532 e f )
+insert ( 11490 602 600 1533 e f )
+insert ( 11491 602 604 1449 a f )
+insert ( 11492 603 600 1534 e f )
+insert ( 11493 603 601 1541 e f )
+insert ( 11494 603 604 1448 a f )
+insert ( 11495 603 718 1479 e f )
+insert ( 11496 604 600 1540 e f )
+insert ( 11497 604 602 1447 a f )
+insert ( 11498 604 603 1446 e f )
+insert ( 11499 604 718 1474 e f )
+insert ( 11500 718 600 1416 e f )
+insert ( 11501 718 603 1480 e f )
+insert ( 11502 718 604 1544 e f )
+insert ( 11503 829 774 4123 i f )
+insert ( 11504 774 829 4124 i f )
+insert ( 11505 650 869 0 i b )
+insert ( 11506 869 650 1715 a f )
+insert ( 11507 1560 1562 0 i b )
+insert ( 11508 1562 1560 0 i b )
+insert ( 11509 20 1560 2075 e f )
+insert ( 11510 23 1560 1683 e f )
+insert ( 11511 1560 20 2076 e f )
+insert ( 11512 1560 23 1684 e f )
+insert ( 11513 650 25 730 a f )
+insert ( 11514 869 25 730 a f )
+insert ( 11515 16 25 2971 a f )
+insert ( 11516 142 25 0 a b )
+insert ( 11517 25 142 2896 e f )
+insert ( 11518 650 1043 730 a f )
+insert ( 11519 869 1043 730 a f )
+insert ( 11520 16 1043 2971 a f )
+insert ( 11521 142 1043 0 a b )
+insert ( 11522 1043 142 2896 e f )
+insert ( 11523 650 1042 730 a f )
+insert ( 11524 869 1042 730 a f )
+insert ( 11525 16 1042 2971 a f )
+insert ( 11526 142 1042 0 a b )
+insert ( 11527 1042 142 2896 e f )
+insert ( 11528 1042 1042 668 i f )
+insert ( 11529 1043 1043 669 i f )
+insert ( 11530 1083 1083 1968 i f )
+insert ( 11531 1114 1114 1961 i f )
+insert ( 11532 1184 1184 1967 i f )
+insert ( 11533 1186 1186 1200 i f )
+insert ( 11534 1266 1266 1969 i f )
+insert ( 11535 1560 1560 1685 i f )
+insert ( 11536 1562 1562 1687 i f )
+insert ( 11537 1700 1700 1703 i f )
+insert ( 11538 114 3802 0 a i )
+insert ( 11539 3802 114 0 a i )
+insert ( 11540 3802 16 3556 e f )
+insert ( 11541 3802 1700 3449 e f )
+insert ( 11542 3802 21 3450 e f )
+insert ( 11543 3802 23 3451 e f )
+insert ( 11544 3802 20 3452 e f )
+insert ( 11545 3802 700 3453 e f )
+insert ( 11546 3802 701 2580 e f )
+close pg_cast
+create pg_enum 3501
+ (
+ oid = oid ,
+ enumtypid = oid ,
+ enumsortorder = float4 ,
+ enumlabel = name
+ )
+open pg_enum
+close pg_enum
+create pg_namespace 2615
+ (
+ oid = oid ,
+ nspname = name ,
+ nspowner = oid ,
+ nspacl = _aclitem
+ )
+open pg_namespace
+insert ( 11 pg_catalog 10 _null_ )
+insert ( 99 pg_toast 10 _null_ )
+insert ( 2200 public 10 _null_ )
+close pg_namespace
+create pg_conversion 2607
+ (
+ oid = oid ,
+ conname = name ,
+ connamespace = oid ,
+ conowner = oid ,
+ conforencoding = int4 ,
+ contoencoding = int4 ,
+ conproc = regproc ,
+ condefault = bool
+ )
+open pg_conversion
+insert ( 4402 koi8_r_to_mic 11 10 22 7 4302 t )
+insert ( 4403 mic_to_koi8_r 11 10 7 22 4303 t )
+insert ( 4404 iso_8859_5_to_mic 11 10 25 7 4304 t )
+insert ( 4405 mic_to_iso_8859_5 11 10 7 25 4305 t )
+insert ( 4406 windows_1251_to_mic 11 10 23 7 4306 t )
+insert ( 4407 mic_to_windows_1251 11 10 7 23 4307 t )
+insert ( 4408 windows_866_to_mic 11 10 20 7 4308 t )
+insert ( 4409 mic_to_windows_866 11 10 7 20 4309 t )
+insert ( 4410 koi8_r_to_windows_1251 11 10 22 23 4310 t )
+insert ( 4411 windows_1251_to_koi8_r 11 10 23 22 4311 t )
+insert ( 4412 koi8_r_to_windows_866 11 10 22 20 4312 t )
+insert ( 4413 windows_866_to_koi8_r 11 10 20 22 4313 t )
+insert ( 4414 windows_866_to_windows_1251 11 10 20 23 4314 t )
+insert ( 4415 windows_1251_to_windows_866 11 10 23 20 4315 t )
+insert ( 4416 iso_8859_5_to_koi8_r 11 10 25 22 4316 t )
+insert ( 4417 koi8_r_to_iso_8859_5 11 10 22 25 4317 t )
+insert ( 4418 iso_8859_5_to_windows_1251 11 10 25 23 4318 t )
+insert ( 4419 windows_1251_to_iso_8859_5 11 10 23 25 4319 t )
+insert ( 4420 iso_8859_5_to_windows_866 11 10 25 20 4320 t )
+insert ( 4421 windows_866_to_iso_8859_5 11 10 20 25 4321 t )
+insert ( 4422 euc_cn_to_mic 11 10 2 7 4322 t )
+insert ( 4423 mic_to_euc_cn 11 10 7 2 4323 t )
+insert ( 4424 euc_jp_to_sjis 11 10 1 35 4324 t )
+insert ( 4425 sjis_to_euc_jp 11 10 35 1 4325 t )
+insert ( 4426 euc_jp_to_mic 11 10 1 7 4326 t )
+insert ( 4427 sjis_to_mic 11 10 35 7 4327 t )
+insert ( 4428 mic_to_euc_jp 11 10 7 1 4328 t )
+insert ( 4429 mic_to_sjis 11 10 7 35 4329 t )
+insert ( 4430 euc_kr_to_mic 11 10 3 7 4330 t )
+insert ( 4431 mic_to_euc_kr 11 10 7 3 4331 t )
+insert ( 4432 euc_tw_to_big5 11 10 4 36 4332 t )
+insert ( 4433 big5_to_euc_tw 11 10 36 4 4333 t )
+insert ( 4434 euc_tw_to_mic 11 10 4 7 4334 t )
+insert ( 4435 big5_to_mic 11 10 36 7 4335 t )
+insert ( 4436 mic_to_euc_tw 11 10 7 4 4336 t )
+insert ( 4437 mic_to_big5 11 10 7 36 4337 t )
+insert ( 4438 iso_8859_2_to_mic 11 10 9 7 4338 t )
+insert ( 4439 mic_to_iso_8859_2 11 10 7 9 4339 t )
+insert ( 4440 windows_1250_to_mic 11 10 29 7 4340 t )
+insert ( 4441 mic_to_windows_1250 11 10 7 29 4341 t )
+insert ( 4442 iso_8859_2_to_windows_1250 11 10 9 29 4342 t )
+insert ( 4443 windows_1250_to_iso_8859_2 11 10 29 9 4343 t )
+insert ( 4444 iso_8859_1_to_mic 11 10 8 7 4344 t )
+insert ( 4445 mic_to_iso_8859_1 11 10 7 8 4345 t )
+insert ( 4446 iso_8859_3_to_mic 11 10 10 7 4346 t )
+insert ( 4447 mic_to_iso_8859_3 11 10 7 10 4347 t )
+insert ( 4448 iso_8859_4_to_mic 11 10 11 7 4348 t )
+insert ( 4449 mic_to_iso_8859_4 11 10 7 11 4349 t )
+insert ( 4452 big5_to_utf8 11 10 36 6 4352 t )
+insert ( 4453 utf8_to_big5 11 10 6 36 4353 t )
+insert ( 4454 utf8_to_koi8_r 11 10 6 22 4354 t )
+insert ( 4455 koi8_r_to_utf8 11 10 22 6 4355 t )
+insert ( 4456 utf8_to_koi8_u 11 10 6 34 4356 t )
+insert ( 4457 koi8_u_to_utf8 11 10 34 6 4357 t )
+insert ( 4458 utf8_to_windows_866 11 10 6 20 4358 t )
+insert ( 4459 windows_866_to_utf8 11 10 20 6 4359 t )
+insert ( 4460 utf8_to_windows_874 11 10 6 21 4358 t )
+insert ( 4461 windows_874_to_utf8 11 10 21 6 4359 t )
+insert ( 4462 utf8_to_windows_1250 11 10 6 29 4358 t )
+insert ( 4463 windows_1250_to_utf8 11 10 29 6 4359 t )
+insert ( 4464 utf8_to_windows_1251 11 10 6 23 4358 t )
+insert ( 4465 windows_1251_to_utf8 11 10 23 6 4359 t )
+insert ( 4466 utf8_to_windows_1252 11 10 6 24 4358 t )
+insert ( 4467 windows_1252_to_utf8 11 10 24 6 4359 t )
+insert ( 4468 utf8_to_windows_1253 11 10 6 30 4358 t )
+insert ( 4469 windows_1253_to_utf8 11 10 30 6 4359 t )
+insert ( 4470 utf8_to_windows_1254 11 10 6 31 4358 t )
+insert ( 4471 windows_1254_to_utf8 11 10 31 6 4359 t )
+insert ( 4472 utf8_to_windows_1255 11 10 6 32 4358 t )
+insert ( 4473 windows_1255_to_utf8 11 10 32 6 4359 t )
+insert ( 4474 utf8_to_windows_1256 11 10 6 18 4358 t )
+insert ( 4475 windows_1256_to_utf8 11 10 18 6 4359 t )
+insert ( 4476 utf8_to_windows_1257 11 10 6 33 4358 t )
+insert ( 4477 windows_1257_to_utf8 11 10 33 6 4359 t )
+insert ( 4478 utf8_to_windows_1258 11 10 6 19 4358 t )
+insert ( 4479 windows_1258_to_utf8 11 10 19 6 4359 t )
+insert ( 4480 euc_cn_to_utf8 11 10 2 6 4360 t )
+insert ( 4481 utf8_to_euc_cn 11 10 6 2 4361 t )
+insert ( 4482 euc_jp_to_utf8 11 10 1 6 4362 t )
+insert ( 4483 utf8_to_euc_jp 11 10 6 1 4363 t )
+insert ( 4484 euc_kr_to_utf8 11 10 3 6 4364 t )
+insert ( 4485 utf8_to_euc_kr 11 10 6 3 4365 t )
+insert ( 4486 euc_tw_to_utf8 11 10 4 6 4366 t )
+insert ( 4487 utf8_to_euc_tw 11 10 6 4 4367 t )
+insert ( 4488 gb18030_to_utf8 11 10 39 6 4368 t )
+insert ( 4489 utf8_to_gb18030 11 10 6 39 4369 t )
+insert ( 4490 gbk_to_utf8 11 10 37 6 4370 t )
+insert ( 4491 utf8_to_gbk 11 10 6 37 4371 t )
+insert ( 4492 utf8_to_iso_8859_2 11 10 6 9 4372 t )
+insert ( 4493 iso_8859_2_to_utf8 11 10 9 6 4373 t )
+insert ( 4494 utf8_to_iso_8859_3 11 10 6 10 4372 t )
+insert ( 4495 iso_8859_3_to_utf8 11 10 10 6 4373 t )
+insert ( 4496 utf8_to_iso_8859_4 11 10 6 11 4372 t )
+insert ( 4497 iso_8859_4_to_utf8 11 10 11 6 4373 t )
+insert ( 4498 utf8_to_iso_8859_9 11 10 6 12 4372 t )
+insert ( 4499 iso_8859_9_to_utf8 11 10 12 6 4373 t )
+insert ( 4500 utf8_to_iso_8859_10 11 10 6 13 4372 t )
+insert ( 4501 iso_8859_10_to_utf8 11 10 13 6 4373 t )
+insert ( 4502 utf8_to_iso_8859_13 11 10 6 14 4372 t )
+insert ( 4503 iso_8859_13_to_utf8 11 10 14 6 4373 t )
+insert ( 4504 utf8_to_iso_8859_14 11 10 6 15 4372 t )
+insert ( 4505 iso_8859_14_to_utf8 11 10 15 6 4373 t )
+insert ( 4506 utf8_to_iso_8859_15 11 10 6 16 4372 t )
+insert ( 4507 iso_8859_15_to_utf8 11 10 16 6 4373 t )
+insert ( 4508 utf8_to_iso_8859_16 11 10 6 17 4372 t )
+insert ( 4509 iso_8859_16_to_utf8 11 10 17 6 4373 t )
+insert ( 4510 utf8_to_iso_8859_5 11 10 6 25 4372 t )
+insert ( 4511 iso_8859_5_to_utf8 11 10 25 6 4373 t )
+insert ( 4512 utf8_to_iso_8859_6 11 10 6 26 4372 t )
+insert ( 4513 iso_8859_6_to_utf8 11 10 26 6 4373 t )
+insert ( 4514 utf8_to_iso_8859_7 11 10 6 27 4372 t )
+insert ( 4515 iso_8859_7_to_utf8 11 10 27 6 4373 t )
+insert ( 4516 utf8_to_iso_8859_8 11 10 6 28 4372 t )
+insert ( 4517 iso_8859_8_to_utf8 11 10 28 6 4373 t )
+insert ( 4518 iso_8859_1_to_utf8 11 10 8 6 4374 t )
+insert ( 4519 utf8_to_iso_8859_1 11 10 6 8 4375 t )
+insert ( 4520 johab_to_utf8 11 10 40 6 4376 t )
+insert ( 4521 utf8_to_johab 11 10 6 40 4377 t )
+insert ( 4522 sjis_to_utf8 11 10 35 6 4378 t )
+insert ( 4523 utf8_to_sjis 11 10 6 35 4379 t )
+insert ( 4524 uhc_to_utf8 11 10 38 6 4380 t )
+insert ( 4525 utf8_to_uhc 11 10 6 38 4381 t )
+insert ( 4526 euc_jis_2004_to_utf8 11 10 5 6 4382 t )
+insert ( 4527 utf8_to_euc_jis_2004 11 10 6 5 4383 t )
+insert ( 4528 shift_jis_2004_to_utf8 11 10 41 6 4384 t )
+insert ( 4529 utf8_to_shift_jis_2004 11 10 6 41 4385 t )
+insert ( 4530 euc_jis_2004_to_shift_jis_2004 11 10 5 41 4386 t )
+insert ( 4531 shift_jis_2004_to_euc_jis_2004 11 10 41 5 4387 t )
+close pg_conversion
+create pg_depend 2608
+ (
+ classid = oid ,
+ objid = oid ,
+ objsubid = int4 ,
+ refclassid = oid ,
+ refobjid = oid ,
+ refobjsubid = int4 ,
+ deptype = char
+ )
+open pg_depend
+close pg_depend
+create pg_database 1262 shared_relation rowtype_oid 1248
+ (
+ oid = oid ,
+ datname = name ,
+ datdba = oid ,
+ encoding = int4 ,
+ datcollate = name ,
+ datctype = name ,
+ datistemplate = bool ,
+ datallowconn = bool ,
+ datconnlimit = int4 ,
+ datlastsysoid = oid ,
+ datfrozenxid = xid ,
+ datminmxid = xid ,
+ dattablespace = oid ,
+ datacl = _aclitem
+ )
+open pg_database
+insert ( 1 template1 10 ENCODING LC_COLLATE LC_CTYPE t t -1 0 0 1 1663 _null_ )
+close pg_database
+create pg_db_role_setting 2964 shared_relation
+ (
+ setdatabase = oid ,
+ setrole = oid ,
+ setconfig = _text
+ )
+open pg_db_role_setting
+close pg_db_role_setting
+create pg_tablespace 1213 shared_relation
+ (
+ oid = oid ,
+ spcname = name ,
+ spcowner = oid ,
+ spcacl = _aclitem ,
+ spcoptions = _text
+ )
+open pg_tablespace
+insert ( 1663 pg_default 10 _null_ _null_ )
+insert ( 1664 pg_global 10 _null_ _null_ )
+close pg_tablespace
+create pg_authid 1260 shared_relation rowtype_oid 2842
+ (
+ oid = oid ,
+ rolname = name ,
+ rolsuper = bool ,
+ rolinherit = bool ,
+ rolcreaterole = bool ,
+ rolcreatedb = bool ,
+ rolcanlogin = bool ,
+ rolreplication = bool ,
+ rolbypassrls = bool ,
+ rolconnlimit = int4 ,
+ rolpassword = text ,
+ rolvaliduntil = timestamptz
+ )
+open pg_authid
+insert ( 10 POSTGRES t t t t t t t -1 _null_ _null_ )
+insert ( 3373 pg_monitor f t f f f f f -1 _null_ _null_ )
+insert ( 3374 pg_read_all_settings f t f f f f f -1 _null_ _null_ )
+insert ( 3375 pg_read_all_stats f t f f f f f -1 _null_ _null_ )
+insert ( 3377 pg_stat_scan_tables f t f f f f f -1 _null_ _null_ )
+insert ( 4569 pg_read_server_files f t f f f f f -1 _null_ _null_ )
+insert ( 4570 pg_write_server_files f t f f f f f -1 _null_ _null_ )
+insert ( 4571 pg_execute_server_program f t f f f f f -1 _null_ _null_ )
+insert ( 4200 pg_signal_backend f t f f f f f -1 _null_ _null_ )
+close pg_authid
+create pg_auth_members 1261 shared_relation rowtype_oid 2843
+ (
+ roleid = oid ,
+ member = oid ,
+ grantor = oid ,
+ admin_option = bool
+ )
+open pg_auth_members
+close pg_auth_members
+create pg_shdepend 1214 shared_relation
+ (
+ dbid = oid ,
+ classid = oid ,
+ objid = oid ,
+ objsubid = int4 ,
+ refclassid = oid ,
+ refobjid = oid ,
+ deptype = char
+ )
+open pg_shdepend
+close pg_shdepend
+create pg_shdescription 2396 shared_relation
+ (
+ objoid = oid ,
+ classoid = oid ,
+ description = text FORCE NOT NULL
+ )
+open pg_shdescription
+insert ( 1 1262 "default template for new databases" )
+close pg_shdescription
+create pg_ts_config 3602
+ (
+ oid = oid ,
+ cfgname = name ,
+ cfgnamespace = oid ,
+ cfgowner = oid ,
+ cfgparser = oid
+ )
+open pg_ts_config
+insert ( 3748 simple 11 10 3722 )
+close pg_ts_config
+create pg_ts_config_map 3603
+ (
+ mapcfg = oid ,
+ maptokentype = int4 ,
+ mapseqno = int4 ,
+ mapdict = oid
+ )
+open pg_ts_config_map
+insert ( 3748 1 1 3765 )
+insert ( 3748 2 1 3765 )
+insert ( 3748 3 1 3765 )
+insert ( 3748 4 1 3765 )
+insert ( 3748 5 1 3765 )
+insert ( 3748 6 1 3765 )
+insert ( 3748 7 1 3765 )
+insert ( 3748 8 1 3765 )
+insert ( 3748 9 1 3765 )
+insert ( 3748 10 1 3765 )
+insert ( 3748 11 1 3765 )
+insert ( 3748 15 1 3765 )
+insert ( 3748 16 1 3765 )
+insert ( 3748 17 1 3765 )
+insert ( 3748 18 1 3765 )
+insert ( 3748 19 1 3765 )
+insert ( 3748 20 1 3765 )
+insert ( 3748 21 1 3765 )
+insert ( 3748 22 1 3765 )
+close pg_ts_config_map
+create pg_ts_dict 3600
+ (
+ oid = oid ,
+ dictname = name ,
+ dictnamespace = oid ,
+ dictowner = oid ,
+ dicttemplate = oid ,
+ dictinitoption = text
+ )
+open pg_ts_dict
+insert ( 3765 simple 11 10 3727 _null_ )
+close pg_ts_dict
+create pg_ts_parser 3601
+ (
+ oid = oid ,
+ prsname = name ,
+ prsnamespace = oid ,
+ prsstart = regproc ,
+ prstoken = regproc ,
+ prsend = regproc ,
+ prsheadline = regproc ,
+ prslextype = regproc
+ )
+open pg_ts_parser
+insert ( 3722 default 11 3717 3718 3719 3720 3721 )
+close pg_ts_parser
+create pg_ts_template 3764
+ (
+ oid = oid ,
+ tmplname = name ,
+ tmplnamespace = oid ,
+ tmplinit = regproc ,
+ tmpllexize = regproc
+ )
+open pg_ts_template
+insert ( 3727 simple 11 3725 3726 )
+insert ( 3730 synonym 11 3728 3729 )
+insert ( 3733 ispell 11 3731 3732 )
+insert ( 3742 thesaurus 11 3740 3741 )
+close pg_ts_template
+create pg_extension 3079
+ (
+ oid = oid ,
+ extname = name ,
+ extowner = oid ,
+ extnamespace = oid ,
+ extrelocatable = bool ,
+ extversion = text FORCE NOT NULL ,
+ extconfig = _oid ,
+ extcondition = _text
+ )
+open pg_extension
+close pg_extension
+create pg_foreign_data_wrapper 2328
+ (
+ oid = oid ,
+ fdwname = name ,
+ fdwowner = oid ,
+ fdwhandler = oid ,
+ fdwvalidator = oid ,
+ fdwacl = _aclitem ,
+ fdwoptions = _text
+ )
+open pg_foreign_data_wrapper
+close pg_foreign_data_wrapper
+create pg_foreign_server 1417
+ (
+ oid = oid ,
+ srvname = name ,
+ srvowner = oid ,
+ srvfdw = oid ,
+ srvtype = text ,
+ srvversion = text ,
+ srvacl = _aclitem ,
+ srvoptions = _text
+ )
+open pg_foreign_server
+close pg_foreign_server
+create pg_user_mapping 1418
+ (
+ oid = oid ,
+ umuser = oid ,
+ umserver = oid ,
+ umoptions = _text
+ )
+open pg_user_mapping
+close pg_user_mapping
+create pg_foreign_table 3118
+ (
+ ftrelid = oid ,
+ ftserver = oid ,
+ ftoptions = _text
+ )
+open pg_foreign_table
+close pg_foreign_table
+create pg_policy 3256
+ (
+ oid = oid ,
+ polname = name ,
+ polrelid = oid ,
+ polcmd = char ,
+ polpermissive = bool ,
+ polroles = _oid FORCE NOT NULL ,
+ polqual = pg_node_tree ,
+ polwithcheck = pg_node_tree
+ )
+open pg_policy
+close pg_policy
+create pg_replication_origin 6000 shared_relation
+ (
+ roident = oid ,
+ roname = text FORCE NOT NULL
+ )
+open pg_replication_origin
+close pg_replication_origin
+create pg_default_acl 826
+ (
+ oid = oid ,
+ defaclrole = oid ,
+ defaclnamespace = oid ,
+ defaclobjtype = char ,
+ defaclacl = _aclitem FORCE NOT NULL
+ )
+open pg_default_acl
+close pg_default_acl
+create pg_init_privs 3394
+ (
+ objoid = oid ,
+ classoid = oid ,
+ objsubid = int4 ,
+ privtype = char ,
+ initprivs = _aclitem FORCE NOT NULL
+ )
+open pg_init_privs
+close pg_init_privs
+create pg_seclabel 3596
+ (
+ objoid = oid ,
+ classoid = oid ,
+ objsubid = int4 ,
+ provider = text FORCE NOT NULL ,
+ label = text FORCE NOT NULL
+ )
+open pg_seclabel
+close pg_seclabel
+create pg_shseclabel 3592 shared_relation rowtype_oid 4066
+ (
+ objoid = oid ,
+ classoid = oid ,
+ provider = text FORCE NOT NULL ,
+ label = text FORCE NOT NULL
+ )
+open pg_shseclabel
+close pg_shseclabel
+create pg_collation 3456
+ (
+ oid = oid ,
+ collname = name ,
+ collnamespace = oid ,
+ collowner = oid ,
+ collprovider = char ,
+ collisdeterministic = bool ,
+ collencoding = int4 ,
+ collcollate = name ,
+ collctype = name ,
+ collversion = text
+ )
+open pg_collation
+insert ( 100 default 11 10 d t -1 "" "" _null_ )
+insert ( 950 C 11 10 c t -1 C C _null_ )
+insert ( 951 POSIX 11 10 c t -1 POSIX POSIX _null_ )
+close pg_collation
+create pg_partitioned_table 3350
+ (
+ partrelid = oid ,
+ partstrat = char ,
+ partnatts = int2 ,
+ partdefid = oid ,
+ partattrs = int2vector ,
+ partclass = oidvector ,
+ partcollation = oidvector ,
+ partexprs = pg_node_tree
+ )
+open pg_partitioned_table
+close pg_partitioned_table
+create pg_range 3541
+ (
+ rngtypid = oid ,
+ rngsubtype = oid ,
+ rngcollation = oid ,
+ rngsubopc = oid ,
+ rngcanonical = regproc ,
+ rngsubdiff = regproc
+ )
+open pg_range
+insert ( 3904 23 0 1978 3914 3922 )
+insert ( 3906 1700 0 3125 - 3924 )
+insert ( 3908 1114 0 3128 - 3929 )
+insert ( 3910 1184 0 3127 - 3930 )
+insert ( 3912 1082 0 3122 3915 3925 )
+insert ( 3926 20 0 3124 3928 3923 )
+close pg_range
+create pg_transform 3576
+ (
+ oid = oid ,
+ trftype = oid ,
+ trflang = oid ,
+ trffromsql = regproc ,
+ trftosql = regproc
+ )
+open pg_transform
+close pg_transform
+create pg_sequence 2224
+ (
+ seqrelid = oid ,
+ seqtypid = oid ,
+ seqstart = int8 ,
+ seqincrement = int8 ,
+ seqmax = int8 ,
+ seqmin = int8 ,
+ seqcache = int8 ,
+ seqcycle = bool
+ )
+open pg_sequence
+close pg_sequence
+create pg_publication 6104
+ (
+ oid = oid ,
+ pubname = name ,
+ pubowner = oid ,
+ puballtables = bool ,
+ pubinsert = bool ,
+ pubupdate = bool ,
+ pubdelete = bool ,
+ pubtruncate = bool ,
+ pubviaroot = bool
+ )
+open pg_publication
+close pg_publication
+create pg_publication_rel 6106
+ (
+ oid = oid ,
+ prpubid = oid ,
+ prrelid = oid
+ )
+open pg_publication_rel
+close pg_publication_rel
+create pg_subscription 6100 shared_relation rowtype_oid 6101
+ (
+ oid = oid ,
+ subdbid = oid ,
+ subname = name ,
+ subowner = oid ,
+ subenabled = bool ,
+ subconninfo = text FORCE NOT NULL ,
+ subslotname = name FORCE NULL ,
+ subsynccommit = text FORCE NOT NULL ,
+ subpublications = _text FORCE NOT NULL
+ )
+open pg_subscription
+close pg_subscription
+create pg_subscription_rel 6102
+ (
+ srsubid = oid ,
+ srrelid = oid ,
+ srsubstate = char ,
+ srsublsn = pg_lsn FORCE NULL
+ )
+open pg_subscription_rel
+close pg_subscription_rel
+declare toast 4159 4160 on pg_aggregate
+declare toast 2830 2831 on pg_attrdef
+declare toast 4161 4162 on pg_collation
+declare toast 2832 2833 on pg_constraint
+declare toast 4143 4144 on pg_default_acl
+declare toast 2834 2835 on pg_description
+declare toast 4145 4146 on pg_event_trigger
+declare toast 4147 4148 on pg_extension
+declare toast 4149 4150 on pg_foreign_data_wrapper
+declare toast 4151 4152 on pg_foreign_server
+declare toast 4153 4154 on pg_foreign_table
+declare toast 4155 4156 on pg_init_privs
+declare toast 4157 4158 on pg_language
+declare toast 4163 4164 on pg_namespace
+declare toast 4165 4166 on pg_partitioned_table
+declare toast 4167 4168 on pg_policy
+declare toast 2836 2837 on pg_proc
+declare toast 2838 2839 on pg_rewrite
+declare toast 3598 3599 on pg_seclabel
+declare toast 2840 2841 on pg_statistic
+declare toast 3439 3440 on pg_statistic_ext
+declare toast 3430 3431 on pg_statistic_ext_data
+declare toast 2336 2337 on pg_trigger
+declare toast 4169 4170 on pg_ts_dict
+declare toast 4171 4172 on pg_type
+declare toast 4173 4174 on pg_user_mapping
+declare toast 4175 4176 on pg_authid
+declare toast 4177 4178 on pg_database
+declare toast 2966 2967 on pg_db_role_setting
+declare toast 4181 4182 on pg_replication_origin
+declare toast 2846 2847 on pg_shdescription
+declare toast 4060 4061 on pg_shseclabel
+declare toast 4183 4184 on pg_subscription
+declare toast 4185 4186 on pg_tablespace
+declare unique index pg_aggregate_fnoid_index 2650 on pg_aggregate using btree(aggfnoid oid_ops)
+declare unique index pg_am_name_index 2651 on pg_am using btree(amname name_ops)
+declare unique index pg_am_oid_index 2652 on pg_am using btree(oid oid_ops)
+declare unique index pg_amop_fam_strat_index 2653 on pg_amop using btree(amopfamily oid_ops, amoplefttype oid_ops, amoprighttype oid_ops, amopstrategy int2_ops)
+declare unique index pg_amop_opr_fam_index 2654 on pg_amop using btree(amopopr oid_ops, amoppurpose char_ops, amopfamily oid_ops)
+declare unique index pg_amop_oid_index 2756 on pg_amop using btree(oid oid_ops)
+declare unique index pg_amproc_fam_proc_index 2655 on pg_amproc using btree(amprocfamily oid_ops, amproclefttype oid_ops, amprocrighttype oid_ops, amprocnum int2_ops)
+declare unique index pg_amproc_oid_index 2757 on pg_amproc using btree(oid oid_ops)
+declare unique index pg_attrdef_adrelid_adnum_index 2656 on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops)
+declare unique index pg_attrdef_oid_index 2657 on pg_attrdef using btree(oid oid_ops)
+declare unique index pg_attribute_relid_attnam_index 2658 on pg_attribute using btree(attrelid oid_ops, attname name_ops)
+declare unique index pg_attribute_relid_attnum_index 2659 on pg_attribute using btree(attrelid oid_ops, attnum int2_ops)
+declare unique index pg_authid_rolname_index 2676 on pg_authid using btree(rolname name_ops)
+declare unique index pg_authid_oid_index 2677 on pg_authid using btree(oid oid_ops)
+declare unique index pg_auth_members_role_member_index 2694 on pg_auth_members using btree(roleid oid_ops, member oid_ops)
+declare unique index pg_auth_members_member_role_index 2695 on pg_auth_members using btree(member oid_ops, roleid oid_ops)
+declare unique index pg_cast_oid_index 2660 on pg_cast using btree(oid oid_ops)
+declare unique index pg_cast_source_target_index 2661 on pg_cast using btree(castsource oid_ops, casttarget oid_ops)
+declare unique index pg_class_oid_index 2662 on pg_class using btree(oid oid_ops)
+declare unique index pg_class_relname_nsp_index 2663 on pg_class using btree(relname name_ops, relnamespace oid_ops)
+declare index pg_class_tblspc_relfilenode_index 3455 on pg_class using btree(reltablespace oid_ops, relfilenode oid_ops)
+declare unique index pg_collation_name_enc_nsp_index 3164 on pg_collation using btree(collname name_ops, collencoding int4_ops, collnamespace oid_ops)
+declare unique index pg_collation_oid_index 3085 on pg_collation using btree(oid oid_ops)
+declare index pg_constraint_conname_nsp_index 2664 on pg_constraint using btree(conname name_ops, connamespace oid_ops)
+declare unique index pg_constraint_conrelid_contypid_conname_index 2665 on pg_constraint using btree(conrelid oid_ops, contypid oid_ops, conname name_ops)
+declare index pg_constraint_contypid_index 2666 on pg_constraint using btree(contypid oid_ops)
+declare unique index pg_constraint_oid_index 2667 on pg_constraint using btree(oid oid_ops)
+declare index pg_constraint_conparentid_index 2579 on pg_constraint using btree(conparentid oid_ops)
+declare unique index pg_conversion_default_index 2668 on pg_conversion using btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops, oid oid_ops)
+declare unique index pg_conversion_name_nsp_index 2669 on pg_conversion using btree(conname name_ops, connamespace oid_ops)
+declare unique index pg_conversion_oid_index 2670 on pg_conversion using btree(oid oid_ops)
+declare unique index pg_database_datname_index 2671 on pg_database using btree(datname name_ops)
+declare unique index pg_database_oid_index 2672 on pg_database using btree(oid oid_ops)
+declare index pg_depend_depender_index 2673 on pg_depend using btree(classid oid_ops, objid oid_ops, objsubid int4_ops)
+declare index pg_depend_reference_index 2674 on pg_depend using btree(refclassid oid_ops, refobjid oid_ops, refobjsubid int4_ops)
+declare unique index pg_description_o_c_o_index 2675 on pg_description using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops)
+declare unique index pg_shdescription_o_c_index 2397 on pg_shdescription using btree(objoid oid_ops, classoid oid_ops)
+declare unique index pg_enum_oid_index 3502 on pg_enum using btree(oid oid_ops)
+declare unique index pg_enum_typid_label_index 3503 on pg_enum using btree(enumtypid oid_ops, enumlabel name_ops)
+declare unique index pg_enum_typid_sortorder_index 3534 on pg_enum using btree(enumtypid oid_ops, enumsortorder float4_ops)
+declare index pg_index_indrelid_index 2678 on pg_index using btree(indrelid oid_ops)
+declare unique index pg_index_indexrelid_index 2679 on pg_index using btree(indexrelid oid_ops)
+declare unique index pg_inherits_relid_seqno_index 2680 on pg_inherits using btree(inhrelid oid_ops, inhseqno int4_ops)
+declare index pg_inherits_parent_index 2187 on pg_inherits using btree(inhparent oid_ops)
+declare unique index pg_init_privs_o_c_o_index 3395 on pg_init_privs using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops)
+declare unique index pg_language_name_index 2681 on pg_language using btree(lanname name_ops)
+declare unique index pg_language_oid_index 2682 on pg_language using btree(oid oid_ops)
+declare unique index pg_largeobject_loid_pn_index 2683 on pg_largeobject using btree(loid oid_ops, pageno int4_ops)
+declare unique index pg_largeobject_metadata_oid_index 2996 on pg_largeobject_metadata using btree(oid oid_ops)
+declare unique index pg_namespace_nspname_index 2684 on pg_namespace using btree(nspname name_ops)
+declare unique index pg_namespace_oid_index 2685 on pg_namespace using btree(oid oid_ops)
+declare unique index pg_opclass_am_name_nsp_index 2686 on pg_opclass using btree(opcmethod oid_ops, opcname name_ops, opcnamespace oid_ops)
+declare unique index pg_opclass_oid_index 2687 on pg_opclass using btree(oid oid_ops)
+declare unique index pg_operator_oid_index 2688 on pg_operator using btree(oid oid_ops)
+declare unique index pg_operator_oprname_l_r_n_index 2689 on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops)
+declare unique index pg_opfamily_am_name_nsp_index 2754 on pg_opfamily using btree(opfmethod oid_ops, opfname name_ops, opfnamespace oid_ops)
+declare unique index pg_opfamily_oid_index 2755 on pg_opfamily using btree(oid oid_ops)
+declare unique index pg_proc_oid_index 2690 on pg_proc using btree(oid oid_ops)
+declare unique index pg_proc_proname_args_nsp_index 2691 on pg_proc using btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops)
+declare unique index pg_rewrite_oid_index 2692 on pg_rewrite using btree(oid oid_ops)
+declare unique index pg_rewrite_rel_rulename_index 2693 on pg_rewrite using btree(ev_class oid_ops, rulename name_ops)
+declare unique index pg_sequence_seqrelid_index 5002 on pg_sequence using btree(seqrelid oid_ops)
+declare index pg_shdepend_depender_index 1232 on pg_shdepend using btree(dbid oid_ops, classid oid_ops, objid oid_ops, objsubid int4_ops)
+declare index pg_shdepend_reference_index 1233 on pg_shdepend using btree(refclassid oid_ops, refobjid oid_ops)
+declare unique index pg_statistic_relid_att_inh_index 2696 on pg_statistic using btree(starelid oid_ops, staattnum int2_ops, stainherit bool_ops)
+declare unique index pg_statistic_ext_oid_index 3380 on pg_statistic_ext using btree(oid oid_ops)
+declare unique index pg_statistic_ext_name_index 3997 on pg_statistic_ext using btree(stxname name_ops, stxnamespace oid_ops)
+declare index pg_statistic_ext_relid_index 3379 on pg_statistic_ext using btree(stxrelid oid_ops)
+declare unique index pg_statistic_ext_data_stxoid_index 3433 on pg_statistic_ext_data using btree(stxoid oid_ops)
+declare unique index pg_tablespace_oid_index 2697 on pg_tablespace using btree(oid oid_ops)
+declare unique index pg_tablespace_spcname_index 2698 on pg_tablespace using btree(spcname name_ops)
+declare unique index pg_transform_oid_index 3574 on pg_transform using btree(oid oid_ops)
+declare unique index pg_transform_type_lang_index 3575 on pg_transform using btree(trftype oid_ops, trflang oid_ops)
+declare index pg_trigger_tgconstraint_index 2699 on pg_trigger using btree(tgconstraint oid_ops)
+declare unique index pg_trigger_tgrelid_tgname_index 2701 on pg_trigger using btree(tgrelid oid_ops, tgname name_ops)
+declare unique index pg_trigger_oid_index 2702 on pg_trigger using btree(oid oid_ops)
+declare unique index pg_event_trigger_evtname_index 3467 on pg_event_trigger using btree(evtname name_ops)
+declare unique index pg_event_trigger_oid_index 3468 on pg_event_trigger using btree(oid oid_ops)
+declare unique index pg_ts_config_cfgname_index 3608 on pg_ts_config using btree(cfgname name_ops, cfgnamespace oid_ops)
+declare unique index pg_ts_config_oid_index 3712 on pg_ts_config using btree(oid oid_ops)
+declare unique index pg_ts_config_map_index 3609 on pg_ts_config_map using btree(mapcfg oid_ops, maptokentype int4_ops, mapseqno int4_ops)
+declare unique index pg_ts_dict_dictname_index 3604 on pg_ts_dict using btree(dictname name_ops, dictnamespace oid_ops)
+declare unique index pg_ts_dict_oid_index 3605 on pg_ts_dict using btree(oid oid_ops)
+declare unique index pg_ts_parser_prsname_index 3606 on pg_ts_parser using btree(prsname name_ops, prsnamespace oid_ops)
+declare unique index pg_ts_parser_oid_index 3607 on pg_ts_parser using btree(oid oid_ops)
+declare unique index pg_ts_template_tmplname_index 3766 on pg_ts_template using btree(tmplname name_ops, tmplnamespace oid_ops)
+declare unique index pg_ts_template_oid_index 3767 on pg_ts_template using btree(oid oid_ops)
+declare unique index pg_type_oid_index 2703 on pg_type using btree(oid oid_ops)
+declare unique index pg_type_typname_nsp_index 2704 on pg_type using btree(typname name_ops, typnamespace oid_ops)
+declare unique index pg_foreign_data_wrapper_oid_index 112 on pg_foreign_data_wrapper using btree(oid oid_ops)
+declare unique index pg_foreign_data_wrapper_name_index 548 on pg_foreign_data_wrapper using btree(fdwname name_ops)
+declare unique index pg_foreign_server_oid_index 113 on pg_foreign_server using btree(oid oid_ops)
+declare unique index pg_foreign_server_name_index 549 on pg_foreign_server using btree(srvname name_ops)
+declare unique index pg_user_mapping_oid_index 174 on pg_user_mapping using btree(oid oid_ops)
+declare unique index pg_user_mapping_user_server_index 175 on pg_user_mapping using btree(umuser oid_ops, umserver oid_ops)
+declare unique index pg_foreign_table_relid_index 3119 on pg_foreign_table using btree(ftrelid oid_ops)
+declare unique index pg_default_acl_role_nsp_obj_index 827 on pg_default_acl using btree(defaclrole oid_ops, defaclnamespace oid_ops, defaclobjtype char_ops)
+declare unique index pg_default_acl_oid_index 828 on pg_default_acl using btree(oid oid_ops)
+declare unique index pg_db_role_setting_databaseid_rol_index 2965 on pg_db_role_setting using btree(setdatabase oid_ops, setrole oid_ops)
+declare unique index pg_seclabel_object_index 3597 on pg_seclabel using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops, provider text_ops)
+declare unique index pg_shseclabel_object_index 3593 on pg_shseclabel using btree(objoid oid_ops, classoid oid_ops, provider text_ops)
+declare unique index pg_extension_oid_index 3080 on pg_extension using btree(oid oid_ops)
+declare unique index pg_extension_name_index 3081 on pg_extension using btree(extname name_ops)
+declare unique index pg_range_rngtypid_index 3542 on pg_range using btree(rngtypid oid_ops)
+declare unique index pg_policy_oid_index 3257 on pg_policy using btree(oid oid_ops)
+declare unique index pg_policy_polrelid_polname_index 3258 on pg_policy using btree(polrelid oid_ops, polname name_ops)
+declare unique index pg_replication_origin_roiident_index 6001 on pg_replication_origin using btree(roident oid_ops)
+declare unique index pg_replication_origin_roname_index 6002 on pg_replication_origin using btree(roname text_ops)
+declare unique index pg_partitioned_table_partrelid_index 3351 on pg_partitioned_table using btree(partrelid oid_ops)
+declare unique index pg_publication_oid_index 6110 on pg_publication using btree(oid oid_ops)
+declare unique index pg_publication_pubname_index 6111 on pg_publication using btree(pubname name_ops)
+declare unique index pg_publication_rel_oid_index 6112 on pg_publication_rel using btree(oid oid_ops)
+declare unique index pg_publication_rel_prrelid_prpubid_index 6113 on pg_publication_rel using btree(prrelid oid_ops, prpubid oid_ops)
+declare unique index pg_subscription_oid_index 6114 on pg_subscription using btree(oid oid_ops)
+declare unique index pg_subscription_subname_index 6115 on pg_subscription using btree(subdbid oid_ops, subname name_ops)
+declare unique index pg_subscription_rel_srrelid_srsubid_index 6117 on pg_subscription_rel using btree(srrelid oid_ops, srsubid oid_ops)
+build indices
diff --git a/src/backend/catalog/schemapg.h b/src/backend/catalog/schemapg.h
new file mode 100644
index 0000000..0069a35
--- /dev/null
+++ b/src/backend/catalog/schemapg.h
@@ -0,0 +1,222 @@
+/*-------------------------------------------------------------------------
+ *
+ * schemapg.h
+ * Schema_pg_xxx macros for use by relcache.c
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ * ******************************
+ * *** DO NOT EDIT THIS FILE! ***
+ * ******************************
+ *
+ * It has been GENERATED by src/backend/catalog/genbki.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SCHEMAPG_H
+#define SCHEMAPG_H
+
+#define Schema_pg_proc \
+{ 1255, {"oid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1255, {"pronamespace"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proowner"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"prolang"}, 26, -1, 4, 5, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"procost"}, 700, -1, 4, 6, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"prorows"}, 700, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"provariadic"}, 26, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"prosupport"}, 24, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"prokind"}, 18, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"prosecdef"}, 16, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proleakproof"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proisstrict"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proretset"}, 16, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"provolatile"}, 18, -1, 1, 15, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proparallel"}, 18, -1, 1, 16, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"pronargs"}, 21, -1, 2, 17, 0, -1, -1, true, 'p', 's', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"pronargdefaults"}, 21, -1, 2, 18, 0, -1, -1, true, 'p', 's', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"prorettype"}, 26, -1, 4, 19, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proargtypes"}, 30, -1, -1, 20, 1, -1, -1, false, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proallargtypes"}, 1028, -1, -1, 21, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proargmodes"}, 1002, -1, -1, 22, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"proargnames"}, 1009, -1, -1, 23, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1255, {"proargdefaults"}, 194, -1, -1, 24, 0, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1255, {"protrftypes"}, 1028, -1, -1, 25, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1255, {"prosrc"}, 25, -1, -1, 26, 0, -1, -1, false, 'x', 'i', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1255, {"probin"}, 25, -1, -1, 27, 0, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1255, {"proconfig"}, 1009, -1, -1, 28, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1255, {"proacl"}, 1034, -1, -1, 29, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 0 }
+
+#define Schema_pg_type \
+{ 1247, {"oid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1247, {"typnamespace"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typowner"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typlen"}, 21, -1, 2, 5, 0, -1, -1, true, 'p', 's', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typbyval"}, 16, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typtype"}, 18, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typcategory"}, 18, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typispreferred"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typisdefined"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typdelim"}, 18, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typrelid"}, 26, -1, 4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typelem"}, 26, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typarray"}, 26, -1, 4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typinput"}, 24, -1, 4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typoutput"}, 24, -1, 4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typreceive"}, 24, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typsend"}, 24, -1, 4, 18, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typmodin"}, 24, -1, 4, 19, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typmodout"}, 24, -1, 4, 20, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typanalyze"}, 24, -1, 4, 21, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typalign"}, 18, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typstorage"}, 18, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typnotnull"}, 16, -1, 1, 24, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typbasetype"}, 26, -1, 4, 25, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typtypmod"}, 23, -1, 4, 26, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typndims"}, 23, -1, 4, 27, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typcollation"}, 26, -1, 4, 28, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1247, {"typdefaultbin"}, 194, -1, -1, 29, 0, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1247, {"typdefault"}, 25, -1, -1, 30, 0, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1247, {"typacl"}, 1034, -1, -1, 31, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 0 }
+
+#define Schema_pg_attribute \
+{ 1249, {"attrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1249, {"atttypid"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attstattarget"}, 23, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attlen"}, 21, -1, 2, 5, 0, -1, -1, true, 'p', 's', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attnum"}, 21, -1, 2, 6, 0, -1, -1, true, 'p', 's', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attndims"}, 23, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attcacheoff"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"atttypmod"}, 23, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attbyval"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attstorage"}, 18, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attalign"}, 18, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attnotnull"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"atthasdef"}, 16, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"atthasmissing"}, 16, -1, 1, 15, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attidentity"}, 18, -1, 1, 16, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attgenerated"}, 18, -1, 1, 17, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attisdropped"}, 16, -1, 1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attislocal"}, 16, -1, 1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attinhcount"}, 23, -1, 4, 20, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attcollation"}, 26, -1, 4, 21, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attacl"}, 1034, -1, -1, 22, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1249, {"attoptions"}, 1009, -1, -1, 23, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1249, {"attfdwoptions"}, 1009, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1249, {"attmissingval"}, 2277, -1, -1, 25, 0, -1, -1, false, 'x', 'd', false, false, false, '\0', '\0', false, true, 0, 0 }
+
+#define Schema_pg_class \
+{ 1259, {"oid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1259, {"relnamespace"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"reltype"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"reloftype"}, 26, -1, 4, 5, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relowner"}, 26, -1, 4, 6, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relam"}, 26, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relfilenode"}, 26, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"reltablespace"}, 26, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relpages"}, 23, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"reltuples"}, 700, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relallvisible"}, 23, -1, 4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"reltoastrelid"}, 26, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relhasindex"}, 16, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relisshared"}, 16, -1, 1, 15, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relpersistence"}, 18, -1, 1, 16, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relkind"}, 18, -1, 1, 17, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relnatts"}, 21, -1, 2, 18, 0, -1, -1, true, 'p', 's', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relchecks"}, 21, -1, 2, 19, 0, -1, -1, true, 'p', 's', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relhasrules"}, 16, -1, 1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relhastriggers"}, 16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relhassubclass"}, 16, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relrowsecurity"}, 16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relforcerowsecurity"}, 16, -1, 1, 24, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relispopulated"}, 16, -1, 1, 25, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relreplident"}, 18, -1, 1, 26, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relispartition"}, 16, -1, 1, 27, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relrewrite"}, 26, -1, 4, 28, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relfrozenxid"}, 28, -1, 4, 29, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relminmxid"}, 28, -1, 4, 30, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"relacl"}, 1034, -1, -1, 31, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1259, {"reloptions"}, 1009, -1, -1, 32, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1259, {"relpartbound"}, 194, -1, -1, 33, 0, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }
+
+#define Schema_pg_index \
+{ 2610, {"indexrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indrelid"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indnatts"}, 21, -1, 2, 3, 0, -1, -1, true, 'p', 's', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indnkeyatts"}, 21, -1, 2, 4, 0, -1, -1, true, 'p', 's', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indisunique"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indisprimary"}, 16, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indisexclusion"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indimmediate"}, 16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indisclustered"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indisvalid"}, 16, -1, 1, 10, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indcheckxmin"}, 16, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indisready"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indislive"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indisreplident"}, 16, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indkey"}, 22, -1, -1, 15, 1, -1, -1, false, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indcollation"}, 30, -1, -1, 16, 1, -1, -1, false, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indclass"}, 30, -1, -1, 17, 1, -1, -1, false, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indoption"}, 22, -1, -1, 18, 1, -1, -1, false, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 2610, {"indexprs"}, 194, -1, -1, 19, 0, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 2610, {"indpred"}, 194, -1, -1, 20, 0, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }
+
+#define Schema_pg_database \
+{ 1262, {"oid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"datname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1262, {"datdba"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"encoding"}, 23, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"datcollate"}, 19, -1, NAMEDATALEN, 5, 0, -1, -1, false, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1262, {"datctype"}, 19, -1, NAMEDATALEN, 6, 0, -1, -1, false, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1262, {"datistemplate"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"datallowconn"}, 16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"datconnlimit"}, 23, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"datlastsysoid"}, 26, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"datfrozenxid"}, 28, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"datminmxid"}, 28, -1, 4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"dattablespace"}, 26, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1262, {"datacl"}, 1034, -1, -1, 14, 1, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 0 }
+
+#define Schema_pg_authid \
+{ 1260, {"oid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1260, {"rolname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1260, {"rolsuper"}, 16, -1, 1, 3, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1260, {"rolinherit"}, 16, -1, 1, 4, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1260, {"rolcreaterole"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1260, {"rolcreatedb"}, 16, -1, 1, 6, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1260, {"rolcanlogin"}, 16, -1, 1, 7, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1260, {"rolreplication"}, 16, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1260, {"rolbypassrls"}, 16, -1, 1, 9, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1260, {"rolconnlimit"}, 23, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1260, {"rolpassword"}, 25, -1, -1, 11, 0, -1, -1, false, 'x', 'i', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 1260, {"rolvaliduntil"}, 1184, -1, 8, 12, 0, -1, -1, FLOAT8PASSBYVAL, 'p', 'd', false, false, false, '\0', '\0', false, true, 0, 0 }
+
+#define Schema_pg_auth_members \
+{ 1261, {"roleid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1261, {"member"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1261, {"grantor"}, 26, -1, 4, 3, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 1261, {"admin_option"}, 16, -1, 1, 4, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }
+
+#define Schema_pg_shseclabel \
+{ 3592, {"objoid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 3592, {"classoid"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 3592, {"provider"}, 25, -1, -1, 3, 0, -1, -1, false, 'x', 'i', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 3592, {"label"}, 25, -1, -1, 4, 0, -1, -1, false, 'x', 'i', true, false, false, '\0', '\0', false, true, 0, 950 }
+
+#define Schema_pg_subscription \
+{ 6100, {"oid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 6100, {"subdbid"}, 26, -1, 4, 2, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 6100, {"subname"}, 19, -1, NAMEDATALEN, 3, 0, -1, -1, false, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 6100, {"subowner"}, 26, -1, 4, 4, 0, -1, -1, true, 'p', 'i', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 6100, {"subenabled"}, 16, -1, 1, 5, 0, -1, -1, true, 'p', 'c', true, false, false, '\0', '\0', false, true, 0, 0 }, \
+{ 6100, {"subconninfo"}, 25, -1, -1, 6, 0, -1, -1, false, 'x', 'i', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 6100, {"subslotname"}, 19, -1, NAMEDATALEN, 7, 0, -1, -1, false, 'p', 'c', false, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 6100, {"subsynccommit"}, 25, -1, -1, 8, 0, -1, -1, false, 'x', 'i', true, false, false, '\0', '\0', false, true, 0, 950 }, \
+{ 6100, {"subpublications"}, 1009, -1, -1, 9, 1, -1, -1, false, 'x', 'i', true, false, false, '\0', '\0', false, true, 0, 950 }
+
+#endif /* SCHEMAPG_H */
diff --git a/src/backend/catalog/sql_feature_packages.txt b/src/backend/catalog/sql_feature_packages.txt
new file mode 100644
index 0000000..7c22145
--- /dev/null
+++ b/src/backend/catalog/sql_feature_packages.txt
@@ -0,0 +1,37 @@
+E011 Core
+E021 Core
+E031 Core
+E051 Core
+E061 Core
+E071 Core
+E081 Core
+E091 Core
+E101 Core
+E111 Core
+E121 Core
+E131 Core
+E141 Core
+E151 Core
+E152 Core
+E153 Core
+E161 Core
+E171 Core
+E182 Core
+F021 Core
+F031 Core
+F041 Core
+F051 Core
+F081 Core
+F131 Core
+F181 Core
+F201 Core
+F221 Core
+F261 Core
+F311 Core
+F471 Core
+F481 Core
+F501 Core
+F812 Core
+S011 Core
+T321 Core
+T631 Core
diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt
new file mode 100644
index 0000000..b6e58e8
--- /dev/null
+++ b/src/backend/catalog/sql_features.txt
@@ -0,0 +1,712 @@
+B011 Embedded Ada NO
+B012 Embedded C YES
+B013 Embedded COBOL NO
+B014 Embedded Fortran NO
+B015 Embedded MUMPS NO
+B016 Embedded Pascal NO
+B017 Embedded PL/I NO
+B021 Direct SQL YES
+B031 Basic dynamic SQL NO
+B032 Extended dynamic SQL NO
+B032 Extended dynamic SQL 01 <describe input statement> NO
+B033 Untyped SQL-invoked function arguments NO
+B034 Dynamic specification of cursor attributes NO
+B035 Non-extended descriptor names NO
+B041 Extensions to embedded SQL exception declarations NO
+B051 Enhanced execution rights NO
+B111 Module language Ada NO
+B112 Module language C NO
+B113 Module language COBOL NO
+B114 Module language Fortran NO
+B115 Module language MUMPS NO
+B116 Module language Pascal NO
+B117 Module language PL/I NO
+B121 Routine language Ada NO
+B122 Routine language C NO
+B123 Routine language COBOL NO
+B124 Routine language Fortran NO
+B125 Routine language MUMPS NO
+B126 Routine language Pascal NO
+B127 Routine language PL/I NO
+B128 Routine language SQL NO
+B200 Polymorphic table functions NO
+B201 More than one PTF generic table parameter NO
+B202 PTF Copartitioning NO
+B203 More than one copartition specification NO
+B204 PRUNE WHEN EMPTY NO
+B205 Pass-through columns NO
+B206 PTF descriptor parameters NO
+B207 Cross products of partitionings NO
+B208 PTF component procedure interface NO
+B209 PTF extended names NO
+B211 Module language Ada: VARCHAR and NUMERIC support NO
+B221 Routine language Ada: VARCHAR and NUMERIC support NO
+E011 Numeric data types YES
+E011 Numeric data types 01 INTEGER and SMALLINT data types YES
+E011 Numeric data types 02 REAL, DOUBLE PRECISION, and FLOAT data types YES
+E011 Numeric data types 03 DECIMAL and NUMERIC data types YES
+E011 Numeric data types 04 Arithmetic operators YES
+E011 Numeric data types 05 Numeric comparison YES
+E011 Numeric data types 06 Implicit casting among the numeric data types YES
+E021 Character data types YES
+E021 Character string types 01 CHARACTER data type YES
+E021 Character string types 02 CHARACTER VARYING data type YES
+E021 Character string types 03 Character literals YES
+E021 Character string types 04 CHARACTER_LENGTH function YES trims trailing spaces from CHARACTER values before counting
+E021 Character string types 05 OCTET_LENGTH function YES
+E021 Character string types 06 SUBSTRING function YES
+E021 Character string types 07 Character concatenation YES
+E021 Character string types 08 UPPER and LOWER functions YES
+E021 Character string types 09 TRIM function YES
+E021 Character string types 10 Implicit casting among the character string types YES
+E021 Character string types 11 POSITION function YES
+E021 Character string types 12 Character comparison YES
+E031 Identifiers YES
+E031 Identifiers 01 Delimited identifiers YES
+E031 Identifiers 02 Lower case identifiers YES
+E031 Identifiers 03 Trailing underscore YES
+E051 Basic query specification YES
+E051 Basic query specification 01 SELECT DISTINCT YES
+E051 Basic query specification 02 GROUP BY clause YES
+E051 Basic query specification 04 GROUP BY can contain columns not in <select list> YES
+E051 Basic query specification 05 Select list items can be renamed YES
+E051 Basic query specification 06 HAVING clause YES
+E051 Basic query specification 07 Qualified * in select list YES
+E051 Basic query specification 08 Correlation names in the FROM clause YES
+E051 Basic query specification 09 Rename columns in the FROM clause YES
+E061 Basic predicates and search conditions YES
+E061 Basic predicates and search conditions 01 Comparison predicate YES
+E061 Basic predicates and search conditions 02 BETWEEN predicate YES
+E061 Basic predicates and search conditions 03 IN predicate with list of values YES
+E061 Basic predicates and search conditions 04 LIKE predicate YES
+E061 Basic predicates and search conditions 05 LIKE predicate ESCAPE clause YES
+E061 Basic predicates and search conditions 06 NULL predicate YES
+E061 Basic predicates and search conditions 07 Quantified comparison predicate YES
+E061 Basic predicates and search conditions 08 EXISTS predicate YES
+E061 Basic predicates and search conditions 09 Subqueries in comparison predicate YES
+E061 Basic predicates and search conditions 11 Subqueries in IN predicate YES
+E061 Basic predicates and search conditions 12 Subqueries in quantified comparison predicate YES
+E061 Basic predicates and search conditions 13 Correlated subqueries YES
+E061 Basic predicates and search conditions 14 Search condition YES
+E071 Basic query expressions YES
+E071 Basic query expressions 01 UNION DISTINCT table operator YES
+E071 Basic query expressions 02 UNION ALL table operator YES
+E071 Basic query expressions 03 EXCEPT DISTINCT table operator YES
+E071 Basic query expressions 05 Columns combined via table operators need not have exactly the same data type YES
+E071 Basic query expressions 06 Table operators in subqueries YES
+E081 Basic Privileges YES
+E081 Basic Privileges 01 SELECT privilege YES
+E081 Basic Privileges 02 DELETE privilege YES
+E081 Basic Privileges 03 INSERT privilege at the table level YES
+E081 Basic Privileges 04 UPDATE privilege at the table level YES
+E081 Basic Privileges 05 UPDATE privilege at the column level YES
+E081 Basic Privileges 06 REFERENCES privilege at the table level YES
+E081 Basic Privileges 07 REFERENCES privilege at the column level YES
+E081 Basic Privileges 08 WITH GRANT OPTION YES
+E081 Basic Privileges 09 USAGE privilege YES
+E081 Basic Privileges 10 EXECUTE privilege YES
+E091 Set functions YES
+E091 Set functions 01 AVG YES
+E091 Set functions 02 COUNT YES
+E091 Set functions 03 MAX YES
+E091 Set functions 04 MIN YES
+E091 Set functions 05 SUM YES
+E091 Set functions 06 ALL quantifier YES
+E091 Set functions 07 DISTINCT quantifier YES
+E101 Basic data manipulation YES
+E101 Basic data manipulation 01 INSERT statement YES
+E101 Basic data manipulation 03 Searched UPDATE statement YES
+E101 Basic data manipulation 04 Searched DELETE statement YES
+E111 Single row SELECT statement YES
+E121 Basic cursor support YES
+E121 Basic cursor support 01 DECLARE CURSOR YES
+E121 Basic cursor support 02 ORDER BY columns need not be in select list YES
+E121 Basic cursor support 03 Value expressions in ORDER BY clause YES
+E121 Basic cursor support 04 OPEN statement YES
+E121 Basic cursor support 06 Positioned UPDATE statement YES
+E121 Basic cursor support 07 Positioned DELETE statement YES
+E121 Basic cursor support 08 CLOSE statement YES
+E121 Basic cursor support 10 FETCH statement implicit NEXT YES
+E121 Basic cursor support 17 WITH HOLD cursors YES
+E131 Null value support (nulls in lieu of values) YES
+E141 Basic integrity constraints YES
+E141 Basic integrity constraints 01 NOT NULL constraints YES
+E141 Basic integrity constraints 02 UNIQUE constraints of NOT NULL columns YES
+E141 Basic integrity constraints 03 PRIMARY KEY constraints YES
+E141 Basic integrity constraints 04 Basic FOREIGN KEY constraint with the NO ACTION default for both referential delete action and referential update action YES
+E141 Basic integrity constraints 06 CHECK constraints YES
+E141 Basic integrity constraints 07 Column defaults YES
+E141 Basic integrity constraints 08 NOT NULL inferred on PRIMARY KEY YES
+E141 Basic integrity constraints 10 Names in a foreign key can be specified in any order YES
+E151 Transaction support YES
+E151 Transaction support 01 COMMIT statement YES
+E151 Transaction support 02 ROLLBACK statement YES
+E152 Basic SET TRANSACTION statement YES
+E152 Basic SET TRANSACTION statement 01 SET TRANSACTION statement: ISOLATION LEVEL SERIALIZABLE clause YES
+E152 Basic SET TRANSACTION statement 02 SET TRANSACTION statement: READ ONLY and READ WRITE clauses YES
+E153 Updatable queries with subqueries YES
+E161 SQL comments using leading double minus YES
+E171 SQLSTATE support YES
+E182 Host language binding YES
+F021 Basic information schema YES
+F021 Basic information schema 01 COLUMNS view YES
+F021 Basic information schema 02 TABLES view YES
+F021 Basic information schema 03 VIEWS view YES
+F021 Basic information schema 04 TABLE_CONSTRAINTS view YES
+F021 Basic information schema 05 REFERENTIAL_CONSTRAINTS view YES
+F021 Basic information schema 06 CHECK_CONSTRAINTS view YES
+F031 Basic schema manipulation YES
+F031 Basic schema manipulation 01 CREATE TABLE statement to create persistent base tables YES
+F031 Basic schema manipulation 02 CREATE VIEW statement YES
+F031 Basic schema manipulation 03 GRANT statement YES
+F031 Basic schema manipulation 04 ALTER TABLE statement: ADD COLUMN clause YES
+F031 Basic schema manipulation 13 DROP TABLE statement: RESTRICT clause YES
+F031 Basic schema manipulation 16 DROP VIEW statement: RESTRICT clause YES
+F031 Basic schema manipulation 19 REVOKE statement: RESTRICT clause YES
+F032 CASCADE drop behavior YES
+F033 ALTER TABLE statement: DROP COLUMN clause YES
+F034 Extended REVOKE statement YES
+F034 Extended REVOKE statement 01 REVOKE statement performed by other than the owner of a schema object YES
+F034 Extended REVOKE statement 02 REVOKE statement: GRANT OPTION FOR clause YES
+F034 Extended REVOKE statement 03 REVOKE statement to revoke a privilege that the grantee has WITH GRANT OPTION YES
+F041 Basic joined table YES
+F041 Basic joined table 01 Inner join (but not necessarily the INNER keyword) YES
+F041 Basic joined table 02 INNER keyword YES
+F041 Basic joined table 03 LEFT OUTER JOIN YES
+F041 Basic joined table 04 RIGHT OUTER JOIN YES
+F041 Basic joined table 05 Outer joins can be nested YES
+F041 Basic joined table 07 The inner table in a left or right outer join can also be used in an inner join YES
+F041 Basic joined table 08 All comparison operators are supported (rather than just =) YES
+F051 Basic date and time YES
+F051 Basic date and time 01 DATE data type (including support of DATE literal) YES
+F051 Basic date and time 02 TIME data type (including support of TIME literal) with fractional seconds precision of at least 0 YES
+F051 Basic date and time 03 TIMESTAMP data type (including support of TIMESTAMP literal) with fractional seconds precision of at least 0 and 6 YES
+F051 Basic date and time 04 Comparison predicate on DATE, TIME, and TIMESTAMP data types YES
+F051 Basic date and time 05 Explicit CAST between datetime types and character string types YES
+F051 Basic date and time 06 CURRENT_DATE YES
+F051 Basic date and time 07 LOCALTIME YES
+F051 Basic date and time 08 LOCALTIMESTAMP YES
+F052 Intervals and datetime arithmetic YES
+F053 OVERLAPS predicate YES
+F054 TIMESTAMP in DATE type precedence list NO
+F081 UNION and EXCEPT in views YES
+F111 Isolation levels other than SERIALIZABLE YES
+F111 Isolation levels other than SERIALIZABLE 01 READ UNCOMMITTED isolation level YES
+F111 Isolation levels other than SERIALIZABLE 02 READ COMMITTED isolation level YES
+F111 Isolation levels other than SERIALIZABLE 03 REPEATABLE READ isolation level YES
+F121 Basic diagnostics management NO
+F121 Basic diagnostics management 01 GET DIAGNOSTICS statement NO
+F121 Basic diagnostics management 02 SET TRANSACTION statement: DIAGNOSTICS SIZE clause NO
+F122 Enhanced diagnostics management NO
+F123 All diagnostics NO
+F131 Grouped operations YES
+F131 Grouped operations 01 WHERE, GROUP BY, and HAVING clauses supported in queries with grouped views YES
+F131 Grouped operations 02 Multiple tables supported in queries with grouped views YES
+F131 Grouped operations 03 Set functions supported in queries with grouped views YES
+F131 Grouped operations 04 Subqueries with GROUP BY and HAVING clauses and grouped views YES
+F131 Grouped operations 05 Single row SELECT with GROUP BY and HAVING clauses and grouped views YES
+F171 Multiple schemas per user YES
+F181 Multiple module support YES
+F191 Referential delete actions YES
+F200 TRUNCATE TABLE statement YES
+F201 CAST function YES
+F202 TRUNCATE TABLE: identity column restart option YES
+F221 Explicit defaults YES
+F222 INSERT statement: DEFAULT VALUES clause YES
+F231 Privilege tables YES
+F231 Privilege tables 01 TABLE_PRIVILEGES view YES
+F231 Privilege tables 02 COLUMN_PRIVILEGES view YES
+F231 Privilege tables 03 USAGE_PRIVILEGES view YES
+F251 Domain support YES
+F261 CASE expression YES
+F261 CASE expression 01 Simple CASE YES
+F261 CASE expression 02 Searched CASE YES
+F261 CASE expression 03 NULLIF YES
+F261 CASE expression 04 COALESCE YES
+F262 Extended CASE expression YES
+F263 Comma-separated predicates in simple CASE expression NO
+F271 Compound character literals YES
+F281 LIKE enhancements YES
+F291 UNIQUE predicate NO
+F301 CORRESPONDING in query expressions NO
+F302 INTERSECT table operator YES
+F302 INTERSECT table operator 01 INTERSECT DISTINCT table operator YES
+F302 INTERSECT table operator 02 INTERSECT ALL table operator YES
+F304 EXCEPT ALL table operator YES
+F311 Schema definition statement YES
+F311 Schema definition statement 01 CREATE SCHEMA YES
+F311 Schema definition statement 02 CREATE TABLE for persistent base tables YES
+F311 Schema definition statement 03 CREATE VIEW YES
+F311 Schema definition statement 04 CREATE VIEW: WITH CHECK OPTION YES
+F311 Schema definition statement 05 GRANT statement YES
+F312 MERGE statement NO consider INSERT ... ON CONFLICT DO UPDATE
+F313 Enhanced MERGE statement NO
+F314 MERGE statement with DELETE branch NO
+F321 User authorization YES
+F341 Usage tables NO no ROUTINE_*_USAGE tables
+F361 Subprogram support YES
+F381 Extended schema manipulation YES
+F381 Extended schema manipulation 01 ALTER TABLE statement: ALTER COLUMN clause YES
+F381 Extended schema manipulation 02 ALTER TABLE statement: ADD CONSTRAINT clause YES
+F381 Extended schema manipulation 03 ALTER TABLE statement: DROP CONSTRAINT clause YES
+F382 Alter column data type YES
+F383 Set column not null clause YES
+F384 Drop identity property clause YES
+F385 Drop column generation expression clause YES
+F386 Set identity column generation clause YES
+F391 Long identifiers YES
+F392 Unicode escapes in identifiers YES
+F393 Unicode escapes in literals YES
+F394 Optional normal form specification YES
+F401 Extended joined table YES
+F401 Extended joined table 01 NATURAL JOIN YES
+F401 Extended joined table 02 FULL OUTER JOIN YES
+F401 Extended joined table 04 CROSS JOIN YES
+F402 Named column joins for LOBs, arrays, and multisets YES
+F403 Partitioned joined tables NO
+F404 Range variable for common column names NO
+F411 Time zone specification YES differences regarding literal interpretation
+F421 National character YES
+F431 Read-only scrollable cursors YES
+F431 Read-only scrollable cursors 01 FETCH with explicit NEXT YES
+F431 Read-only scrollable cursors 02 FETCH FIRST YES
+F431 Read-only scrollable cursors 03 FETCH LAST YES
+F431 Read-only scrollable cursors 04 FETCH PRIOR YES
+F431 Read-only scrollable cursors 05 FETCH ABSOLUTE YES
+F431 Read-only scrollable cursors 06 FETCH RELATIVE YES
+F441 Extended set function support YES
+F442 Mixed column references in set functions YES
+F451 Character set definition NO
+F461 Named character sets NO
+F471 Scalar subquery values YES
+F481 Expanded NULL predicate YES
+F491 Constraint management YES
+F492 Optional table constraint enforcement NO
+F501 Features and conformance views YES
+F501 Features and conformance views 01 SQL_FEATURES view YES
+F501 Features and conformance views 02 SQL_SIZING view YES
+F502 Enhanced documentation tables YES
+F521 Assertions NO
+F531 Temporary tables YES
+F555 Enhanced seconds precision YES
+F561 Full value expressions YES
+F571 Truth value tests YES
+F591 Derived tables YES
+F611 Indicator data types YES
+F641 Row and table constructors YES
+F651 Catalog name qualifiers YES
+F661 Simple tables YES
+F671 Subqueries in CHECK NO intentionally omitted
+F672 Retrospective check constraints YES
+F673 Reads SQL-data routine invocations in CHECK constraints NO
+F690 Collation support YES but no character set support
+F692 Extended collation support YES
+F693 SQL-session and client module collations NO
+F695 Translation support NO
+F696 Additional translation documentation NO
+F701 Referential update actions YES
+F711 ALTER domain YES
+F721 Deferrable constraints NO foreign and unique keys only
+F731 INSERT column privileges YES
+F741 Referential MATCH types NO no partial match yet
+F751 View CHECK enhancements YES
+F761 Session management YES
+F762 CURRENT_CATALOG YES
+F763 CURRENT_SCHEMA YES
+F771 Connection management YES
+F781 Self-referencing operations YES
+F791 Insensitive cursors YES
+F801 Full set function YES
+F812 Basic flagging NO
+F813 Extended flagging NO
+F821 Local table references NO
+F831 Full cursor update NO
+F831 Full cursor update 01 Updatable scrollable cursors NO
+F831 Full cursor update 02 Updatable ordered cursors NO
+F841 LIKE_REGEX predicate NO
+F842 OCCURRENCES_REGEX function NO
+F843 POSITION_REGEX function NO
+F844 SUBSTRING_REGEX function NO
+F845 TRANSLATE_REGEX function NO
+F846 Octet support in regular expression operators NO
+F847 Nonconstant regular expressions NO
+F850 Top-level <order by clause> in <query expression> YES
+F851 <order by clause> in subqueries YES
+F852 Top-level <order by clause> in views YES
+F855 Nested <order by clause> in <query expression> YES
+F856 Nested <fetch first clause> in <query expression> YES
+F857 Top-level <fetch first clause> in <query expression> YES
+F858 <fetch first clause> in subqueries YES
+F859 Top-level <fetch first clause> in views YES
+F860 <fetch first row count> in <fetch first clause> YES
+F861 Top-level <result offset clause> in <query expression> YES
+F862 <result offset clause> in subqueries YES
+F863 Nested <result offset clause> in <query expression> YES
+F864 Top-level <result offset clause> in views YES
+F865 <offset row count> in <result offset clause> YES
+F866 FETCH FIRST clause: PERCENT option NO
+F867 FETCH FIRST clause: WITH TIES option YES
+R010 Row pattern recognition: FROM clause NO
+R020 Row pattern recognition: WINDOW clause NO
+R030 Row pattern recognition: full aggregate support NO
+S011 Distinct data types NO
+S011 Distinct data types 01 USER_DEFINED_TYPES view NO
+S023 Basic structured types NO
+S024 Enhanced structured types NO
+S025 Final structured types NO
+S026 Self-referencing structured types NO
+S027 Create method by specific method name NO
+S028 Permutable UDT options list NO
+S041 Basic reference types NO
+S043 Enhanced reference types NO
+S051 Create table of type NO partially supported
+S071 SQL paths in function and type name resolution YES
+S081 Subtables NO
+S091 Basic array support NO partially supported
+S091 Basic array support 01 Arrays of built-in data types NO
+S091 Basic array support 02 Arrays of distinct types NO
+S091 Basic array support 03 Array expressions NO
+S092 Arrays of user-defined types YES
+S094 Arrays of reference types NO
+S095 Array constructors by query YES
+S096 Optional array bounds YES
+S097 Array element assignment NO
+S098 ARRAY_AGG YES
+S111 ONLY in query expressions YES
+S151 Type predicate NO
+S161 Subtype treatment NO
+S162 Subtype treatment for references NO
+S201 SQL-invoked routines on arrays YES
+S201 SQL-invoked routines on arrays 01 Array parameters YES
+S201 SQL-invoked routines on arrays 02 Array as result type of functions YES
+S202 SQL-invoked routines on multisets NO
+S211 User-defined cast functions YES
+S231 Structured type locators NO
+S232 Array locators NO
+S233 Multiset locators NO
+S241 Transform functions NO
+S242 Alter transform statement NO
+S251 User-defined orderings NO
+S261 Specific type method NO
+S271 Basic multiset support NO
+S272 Multisets of user-defined types NO
+S274 Multisets of reference types NO
+S275 Advanced multiset support NO
+S281 Nested collection types NO
+S291 Unique constraint on entire row NO
+S301 Enhanced UNNEST YES
+S401 Distinct types based on array types NO
+S402 Distinct types based on distinct types NO
+S403 ARRAY_MAX_CARDINALITY NO
+S404 TRIM_ARRAY NO
+T011 Timestamp in Information Schema NO
+T021 BINARY and VARBINARY data types NO
+T022 Advanced support for BINARY and VARBINARY data types NO
+T023 Compound binary literal NO
+T024 Spaces in binary literals NO
+T031 BOOLEAN data type YES
+T041 Basic LOB data type support NO
+T041 Basic LOB data type support 01 BLOB data type NO
+T041 Basic LOB data type support 02 CLOB data type NO
+T041 Basic LOB data type support 03 POSITION, LENGTH, LOWER, TRIM, UPPER, and SUBSTRING functions for LOB data types NO
+T041 Basic LOB data type support 04 Concatenation of LOB data types NO
+T041 Basic LOB data type support 05 LOB locator: non-holdable NO
+T042 Extended LOB data type support NO
+T043 Multiplier T NO
+T044 Multiplier P NO
+T051 Row types NO
+T053 Explicit aliases for all-fields reference NO
+T061 UCS support NO
+T071 BIGINT data type YES
+T076 DECFLOAT data type NO
+T101 Enhanced nullability determination NO
+T111 Updatable joins, unions, and columns NO
+T121 WITH (excluding RECURSIVE) in query expression YES
+T122 WITH (excluding RECURSIVE) in subquery YES
+T131 Recursive query YES
+T132 Recursive query in subquery YES
+T141 SIMILAR predicate YES
+T151 DISTINCT predicate YES
+T152 DISTINCT predicate with negation YES
+T171 LIKE clause in table definition YES
+T172 AS subquery clause in table definition YES
+T173 Extended LIKE clause in table definition YES
+T174 Identity columns YES
+T175 Generated columns NO mostly supported
+T176 Sequence generator support NO supported except for NEXT VALUE FOR
+T177 Sequence generator support: simple restart option YES
+T178 Identity columns: simple restart option YES
+T180 System-versioned tables NO
+T181 Application-time period tables NO
+T191 Referential action RESTRICT YES
+T201 Comparable data types for referential constraints YES
+T211 Basic trigger capability NO
+T211 Basic trigger capability 01 Triggers activated on UPDATE, INSERT, or DELETE of one base table YES
+T211 Basic trigger capability 02 BEFORE triggers YES
+T211 Basic trigger capability 03 AFTER triggers YES
+T211 Basic trigger capability 04 FOR EACH ROW triggers YES
+T211 Basic trigger capability 05 Ability to specify a search condition that must be true before the trigger is invoked YES
+T211 Basic trigger capability 06 Support for run-time rules for the interaction of triggers and constraints NO
+T211 Basic trigger capability 07 TRIGGER privilege YES
+T211 Basic trigger capability 08 Multiple triggers for the same event are executed in the order in which they were created in the catalog NO intentionally omitted
+T212 Enhanced trigger capability YES
+T213 INSTEAD OF triggers YES
+T231 Sensitive cursors YES
+T241 START TRANSACTION statement YES
+T251 SET TRANSACTION statement: LOCAL option NO
+T261 Chained transactions YES
+T271 Savepoints YES
+T272 Enhanced savepoint management NO
+T281 SELECT privilege with column granularity YES
+T285 Enhanced derived column names YES
+T301 Functional dependencies NO partially supported
+T312 OVERLAY function YES
+T321 Basic SQL-invoked routines NO
+T321 Basic SQL-invoked routines 01 User-defined functions with no overloading YES
+T321 Basic SQL-invoked routines 02 User-defined stored procedures with no overloading YES
+T321 Basic SQL-invoked routines 03 Function invocation YES
+T321 Basic SQL-invoked routines 04 CALL statement YES
+T321 Basic SQL-invoked routines 05 RETURN statement NO
+T321 Basic SQL-invoked routines 06 ROUTINES view YES
+T321 Basic SQL-invoked routines 07 PARAMETERS view YES
+T322 Declared data type attributes NO
+T323 Explicit security for external routines YES
+T324 Explicit security for SQL routines NO
+T325 Qualified SQL parameter references YES
+T326 Table functions NO
+T331 Basic roles YES
+T332 Extended roles NO mostly supported
+T341 Overloading of SQL-invoked functions and procedures YES
+T351 Bracketed SQL comments (/*...*/ comments) YES
+T431 Extended grouping capabilities YES
+T432 Nested and concatenated GROUPING SETS YES
+T433 Multiargument GROUPING function YES
+T434 GROUP BY DISTINCT NO
+T441 ABS and MOD functions YES
+T461 Symmetric BETWEEN predicate YES
+T471 Result sets return value NO
+T472 DESCRIBE CURSOR NO
+T491 LATERAL derived table YES
+T495 Combined data change and retrieval NO different syntax
+T501 Enhanced EXISTS predicate YES
+T502 Period predicates NO
+T511 Transaction counts NO
+T521 Named arguments in CALL statement YES
+T522 Default values for IN parameters of SQL-invoked procedures NO supported except DEFAULT key word in invocation
+T523 Default values for INOUT parameters of SQL-invoked procedures YES
+T524 Named arguments in routine invocations other than a CALL statement YES
+T525 Default values for parameters of SQL-invoked functions YES
+T551 Optional key words for default syntax YES
+T561 Holdable locators NO
+T571 Array-returning external SQL-invoked functions NO
+T572 Multiset-returning external SQL-invoked functions NO
+T581 Regular expression substring function YES
+T591 UNIQUE constraints of possibly null columns YES
+T601 Local cursor references NO
+T611 Elementary OLAP operations YES
+T612 Advanced OLAP operations YES
+T613 Sampling YES
+T614 NTILE function YES
+T615 LEAD and LAG functions YES
+T616 Null treatment option for LEAD and LAG functions NO
+T617 FIRST_VALUE and LAST_VALUE function YES
+T618 NTH_VALUE function NO function exists, but some options missing
+T619 Nested window functions NO
+T620 WINDOW clause: GROUPS option YES
+T621 Enhanced numeric functions YES
+T622 Trigonometric functions YES
+T623 General logarithm functions YES
+T624 Common logarithm functions YES
+T625 LISTAGG NO
+T631 IN predicate with one list element YES
+T641 Multiple column assignment NO only some syntax variants supported
+T651 SQL-schema statements in SQL routines YES
+T652 SQL-dynamic statements in SQL routines NO
+T653 SQL-schema statements in external routines YES
+T654 SQL-dynamic statements in external routines NO
+T655 Cyclically dependent routines YES
+T811 Basic SQL/JSON constructor functions NO
+T812 SQL/JSON: JSON_OBJECTAGG NO
+T813 SQL/JSON: JSON_ARRAYAGG with ORDER BY NO
+T814 Colon in JSON_OBJECT or JSON_OBJECTAGG NO
+T821 Basic SQL/JSON query operators NO
+T822 SQL/JSON: IS JSON WITH UNIQUE KEYS predicate NO
+T823 SQL/JSON: PASSING clause NO
+T824 JSON_TABLE: specific PLAN clause NO
+T825 SQL/JSON: ON EMPTY and ON ERROR clauses NO
+T826 General value expression in ON ERROR or ON EMPTY clauses NO
+T827 JSON_TABLE: sibling NESTED COLUMNS clauses NO
+T828 JSON_QUERY NO
+T829 JSON_QUERY: array wrapper options NO
+T830 Enforcing unique keys in SQL/JSON constructor functions NO
+T831 SQL/JSON path language: strict mode YES
+T832 SQL/JSON path language: item method YES
+T833 SQL/JSON path language: multiple subscripts YES
+T834 SQL/JSON path language: wildcard member accessor YES
+T835 SQL/JSON path language: filter expressions YES
+T836 SQL/JSON path language: starts with predicate YES
+T837 SQL/JSON path language: regex_like predicate YES
+T838 JSON_TABLE: PLAN DEFAULT clause NO
+T839 Formatted cast of datetimes to/from character strings NO
+M001 Datalinks NO
+M002 Datalinks via SQL/CLI NO
+M003 Datalinks via Embedded SQL NO
+M004 Foreign data support NO partially supported
+M005 Foreign schema support NO
+M006 GetSQLString routine NO
+M007 TransmitRequest NO
+M009 GetOpts and GetStatistics routines NO
+M010 Foreign data wrapper support NO different API
+M011 Datalinks via Ada NO
+M012 Datalinks via C NO
+M013 Datalinks via COBOL NO
+M014 Datalinks via Fortran NO
+M015 Datalinks via M NO
+M016 Datalinks via Pascal NO
+M017 Datalinks via PL/I NO
+M018 Foreign data wrapper interface routines in Ada NO
+M019 Foreign data wrapper interface routines in C NO different API
+M020 Foreign data wrapper interface routines in COBOL NO
+M021 Foreign data wrapper interface routines in Fortran NO
+M022 Foreign data wrapper interface routines in MUMPS NO
+M023 Foreign data wrapper interface routines in Pascal NO
+M024 Foreign data wrapper interface routines in PL/I NO
+M030 SQL-server foreign data support NO
+M031 Foreign data wrapper general routines NO
+X010 XML type YES
+X011 Arrays of XML type YES
+X012 Multisets of XML type NO
+X013 Distinct types of XML type NO
+X014 Attributes of XML type YES
+X015 Fields of XML type NO
+X016 Persistent XML values YES
+X020 XMLConcat YES
+X025 XMLCast NO
+X030 XMLDocument NO
+X031 XMLElement YES
+X032 XMLForest YES
+X034 XMLAgg YES
+X035 XMLAgg: ORDER BY option YES
+X036 XMLComment YES
+X037 XMLPI YES
+X038 XMLText NO
+X040 Basic table mapping YES
+X041 Basic table mapping: nulls absent YES
+X042 Basic table mapping: null as nil YES
+X043 Basic table mapping: table as forest YES
+X044 Basic table mapping: table as element YES
+X045 Basic table mapping: with target namespace YES
+X046 Basic table mapping: data mapping YES
+X047 Basic table mapping: metadata mapping YES
+X048 Basic table mapping: base64 encoding of binary strings YES
+X049 Basic table mapping: hex encoding of binary strings YES
+X050 Advanced table mapping YES
+X051 Advanced table mapping: nulls absent YES
+X052 Advanced table mapping: null as nil YES
+X053 Advanced table mapping: table as forest YES
+X054 Advanced table mapping: table as element YES
+X055 Advanced table mapping: with target namespace YES
+X056 Advanced table mapping: data mapping YES
+X057 Advanced table mapping: metadata mapping YES
+X058 Advanced table mapping: base64 encoding of binary strings YES
+X059 Advanced table mapping: hex encoding of binary strings YES
+X060 XMLParse: character string input and CONTENT option YES
+X061 XMLParse: character string input and DOCUMENT option YES
+X065 XMLParse: BLOB input and CONTENT option NO
+X066 XMLParse: BLOB input and DOCUMENT option NO
+X068 XMLSerialize: BOM NO
+X069 XMLSerialize: INDENT NO
+X070 XMLSerialize: character string serialization and CONTENT option YES
+X071 XMLSerialize: character string serialization and DOCUMENT option YES
+X072 XMLSerialize: character string serialization YES
+X073 XMLSerialize: BLOB serialization and CONTENT option NO
+X074 XMLSerialize: BLOB serialization and DOCUMENT option NO
+X075 XMLSerialize: BLOB serialization NO
+X076 XMLSerialize: VERSION NO
+X077 XMLSerialize: explicit ENCODING option NO
+X078 XMLSerialize: explicit XML declaration NO
+X080 Namespaces in XML publishing NO
+X081 Query-level XML namespace declarations NO
+X082 XML namespace declarations in DML NO
+X083 XML namespace declarations in DDL NO
+X084 XML namespace declarations in compound statements NO
+X085 Predefined namespace prefixes NO
+X086 XML namespace declarations in XMLTable NO
+X090 XML document predicate YES
+X091 XML content predicate NO
+X096 XMLExists NO XPath 1.0 only
+X100 Host language support for XML: CONTENT option NO
+X101 Host language support for XML: DOCUMENT option NO
+X110 Host language support for XML: VARCHAR mapping NO
+X111 Host language support for XML: CLOB mapping NO
+X112 Host language support for XML: BLOB mapping NO
+X113 Host language support for XML: STRIP WHITESPACE option NO
+X114 Host language support for XML: PRESERVE WHITESPACE option NO
+X120 XML parameters in SQL routines YES
+X121 XML parameters in external routines YES
+X131 Query-level XMLBINARY clause NO
+X132 XMLBINARY clause in DML NO
+X133 XMLBINARY clause in DDL NO
+X134 XMLBINARY clause in compound statements NO
+X135 XMLBINARY clause in subqueries NO
+X141 IS VALID predicate: data-driven case NO
+X142 IS VALID predicate: ACCORDING TO clause NO
+X143 IS VALID predicate: ELEMENT clause NO
+X144 IS VALID predicate: schema location NO
+X145 IS VALID predicate outside check constraints NO
+X151 IS VALID predicate with DOCUMENT option NO
+X152 IS VALID predicate with CONTENT option NO
+X153 IS VALID predicate with SEQUENCE option NO
+X155 IS VALID predicate: NAMESPACE without ELEMENT clause NO
+X157 IS VALID predicate: NO NAMESPACE with ELEMENT clause NO
+X160 Basic Information Schema for registered XML Schemas NO
+X161 Advanced Information Schema for registered XML Schemas NO
+X170 XML null handling options NO
+X171 NIL ON NO CONTENT option NO
+X181 XML(DOCUMENT(UNTYPED)) type NO
+X182 XML(DOCUMENT(ANY)) type NO
+X190 XML(SEQUENCE) type NO
+X191 XML(DOCUMENT(XMLSCHEMA)) type NO
+X192 XML(CONTENT(XMLSCHEMA)) type NO
+X200 XMLQuery NO
+X201 XMLQuery: RETURNING CONTENT NO
+X202 XMLQuery: RETURNING SEQUENCE NO
+X203 XMLQuery: passing a context item NO
+X204 XMLQuery: initializing an XQuery variable NO
+X205 XMLQuery: EMPTY ON EMPTY option NO
+X206 XMLQuery: NULL ON EMPTY option NO
+X211 XML 1.1 support NO
+X221 XML passing mechanism BY VALUE YES
+X222 XML passing mechanism BY REF NO parser accepts BY REF but ignores it; passing is always BY VALUE
+X231 XML(CONTENT(UNTYPED)) type NO
+X232 XML(CONTENT(ANY)) type NO
+X241 RETURNING CONTENT in XML publishing NO
+X242 RETURNING SEQUENCE in XML publishing NO
+X251 Persistent XML values of XML(DOCUMENT(UNTYPED)) type NO
+X252 Persistent XML values of XML(DOCUMENT(ANY)) type NO
+X253 Persistent XML values of XML(CONTENT(UNTYPED)) type NO
+X254 Persistent XML values of XML(CONTENT(ANY)) type NO
+X255 Persistent XML values of XML(SEQUENCE) type NO
+X256 Persistent XML values of XML(DOCUMENT(XMLSCHEMA)) type NO
+X257 Persistent XML values of XML(CONTENT(XMLSCHEMA)) type NO
+X260 XML type: ELEMENT clause NO
+X261 XML type: NAMESPACE without ELEMENT clause NO
+X263 XML type: NO NAMESPACE with ELEMENT clause NO
+X264 XML type: schema location NO
+X271 XMLValidate: data-driven case NO
+X272 XMLValidate: ACCORDING TO clause NO
+X273 XMLValidate: ELEMENT clause NO
+X274 XMLValidate: schema location NO
+X281 XMLValidate with DOCUMENT option NO
+X282 XMLValidate with CONTENT option NO
+X283 XMLValidate with SEQUENCE option NO
+X284 XMLValidate: NAMESPACE without ELEMENT clause NO
+X286 XMLValidate: NO NAMESPACE with ELEMENT clause NO
+X300 XMLTable NO XPath 1.0 only
+X301 XMLTable: derived column list option YES
+X302 XMLTable: ordinality column option YES
+X303 XMLTable: column default option YES
+X304 XMLTable: passing a context item YES must be XML DOCUMENT
+X305 XMLTable: initializing an XQuery variable NO
+X400 Name and identifier mapping YES
+X410 Alter column data type: XML type YES
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
new file mode 100644
index 0000000..7421678
--- /dev/null
+++ b/src/backend/catalog/storage.c
@@ -0,0 +1,1011 @@
+/*-------------------------------------------------------------------------
+ *
+ * storage.c
+ * code to create and destroy physical storage for relations
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/storage.c
+ *
+ * NOTES
+ * Some of this code used to be in storage/smgr/smgr.c, and the
+ * function names still reflect that.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/parallel.h"
+#include "access/visibilitymap.h"
+#include "access/xact.h"
+#include "access/xlog.h"
+#include "access/xloginsert.h"
+#include "access/xlogutils.h"
+#include "catalog/storage.h"
+#include "catalog/storage_xlog.h"
+#include "miscadmin.h"
+#include "storage/freespace.h"
+#include "storage/smgr.h"
+#include "utils/hsearch.h"
+#include "utils/memutils.h"
+#include "utils/rel.h"
+
+/* GUC variables */
+int wal_skip_threshold = 2048; /* in kilobytes */
+
+/*
+ * We keep a list of all relations (represented as RelFileNode values)
+ * that have been created or deleted in the current transaction. When
+ * a relation is created, we create the physical file immediately, but
+ * remember it so that we can delete the file again if the current
+ * transaction is aborted. Conversely, a deletion request is NOT
+ * executed immediately, but is just entered in the list. When and if
+ * the transaction commits, we can delete the physical file.
+ *
+ * To handle subtransactions, every entry is marked with its transaction
+ * nesting level. At subtransaction commit, we reassign the subtransaction's
+ * entries to the parent nesting level. At subtransaction abort, we can
+ * immediately execute the abort-time actions for all entries of the current
+ * nesting level.
+ *
+ * NOTE: the list is kept in TopMemoryContext to be sure it won't disappear
+ * unbetimes. It'd probably be OK to keep it in TopTransactionContext,
+ * but I'm being paranoid.
+ */
+
+typedef struct PendingRelDelete
+{
+ RelFileNode relnode; /* relation that may need to be deleted */
+ BackendId backend; /* InvalidBackendId if not a temp rel */
+ bool atCommit; /* T=delete at commit; F=delete at abort */
+ int nestLevel; /* xact nesting level of request */
+ struct PendingRelDelete *next; /* linked-list link */
+} PendingRelDelete;
+
+typedef struct PendingRelSync
+{
+ RelFileNode rnode;
+ bool is_truncated; /* Has the file experienced truncation? */
+} PendingRelSync;
+
+static PendingRelDelete *pendingDeletes = NULL; /* head of linked list */
+HTAB *pendingSyncHash = NULL;
+
+
+/*
+ * AddPendingSync
+ * Queue an at-commit fsync.
+ */
+static void
+AddPendingSync(const RelFileNode *rnode)
+{
+ PendingRelSync *pending;
+ bool found;
+
+ /* create the hash if not yet */
+ if (!pendingSyncHash)
+ {
+ HASHCTL ctl;
+
+ ctl.keysize = sizeof(RelFileNode);
+ ctl.entrysize = sizeof(PendingRelSync);
+ ctl.hcxt = TopTransactionContext;
+ pendingSyncHash = hash_create("pending sync hash", 16, &ctl,
+ HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+ }
+
+ pending = hash_search(pendingSyncHash, rnode, HASH_ENTER, &found);
+ Assert(!found);
+ pending->is_truncated = false;
+}
+
+/*
+ * RelationCreateStorage
+ * Create physical storage for a relation.
+ *
+ * Create the underlying disk file storage for the relation. This only
+ * creates the main fork; additional forks are created lazily by the
+ * modules that need them.
+ *
+ * This function is transactional. The creation is WAL-logged, and if the
+ * transaction aborts later on, the storage will be destroyed.
+ */
+SMgrRelation
+RelationCreateStorage(RelFileNode rnode, char relpersistence)
+{
+ PendingRelDelete *pending;
+ SMgrRelation srel;
+ BackendId backend;
+ bool needs_wal;
+
+ Assert(!IsInParallelMode()); /* couldn't update pendingSyncHash */
+
+ switch (relpersistence)
+ {
+ case RELPERSISTENCE_TEMP:
+ backend = BackendIdForTempRelations();
+ needs_wal = false;
+ break;
+ case RELPERSISTENCE_UNLOGGED:
+ backend = InvalidBackendId;
+ needs_wal = false;
+ break;
+ case RELPERSISTENCE_PERMANENT:
+ backend = InvalidBackendId;
+ needs_wal = true;
+ break;
+ default:
+ elog(ERROR, "invalid relpersistence: %c", relpersistence);
+ return NULL; /* placate compiler */
+ }
+
+ srel = smgropen(rnode, backend);
+ smgrcreate(srel, MAIN_FORKNUM, false);
+
+ if (needs_wal)
+ log_smgrcreate(&srel->smgr_rnode.node, MAIN_FORKNUM);
+
+ /* Add the relation to the list of stuff to delete at abort */
+ pending = (PendingRelDelete *)
+ MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
+ pending->relnode = rnode;
+ pending->backend = backend;
+ pending->atCommit = false; /* delete if abort */
+ pending->nestLevel = GetCurrentTransactionNestLevel();
+ pending->next = pendingDeletes;
+ pendingDeletes = pending;
+
+ if (relpersistence == RELPERSISTENCE_PERMANENT && !XLogIsNeeded())
+ {
+ Assert(backend == InvalidBackendId);
+ AddPendingSync(&rnode);
+ }
+
+ return srel;
+}
+
+/*
+ * Perform XLogInsert of an XLOG_SMGR_CREATE record to WAL.
+ */
+void
+log_smgrcreate(const RelFileNode *rnode, ForkNumber forkNum)
+{
+ xl_smgr_create xlrec;
+
+ /*
+ * Make an XLOG entry reporting the file creation.
+ */
+ xlrec.rnode = *rnode;
+ xlrec.forkNum = forkNum;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, sizeof(xlrec));
+ XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE | XLR_SPECIAL_REL_UPDATE);
+}
+
+/*
+ * RelationDropStorage
+ * Schedule unlinking of physical storage at transaction commit.
+ */
+void
+RelationDropStorage(Relation rel)
+{
+ PendingRelDelete *pending;
+
+ /* Add the relation to the list of stuff to delete at commit */
+ pending = (PendingRelDelete *)
+ MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
+ pending->relnode = rel->rd_node;
+ pending->backend = rel->rd_backend;
+ pending->atCommit = true; /* delete if commit */
+ pending->nestLevel = GetCurrentTransactionNestLevel();
+ pending->next = pendingDeletes;
+ pendingDeletes = pending;
+
+ /*
+ * NOTE: if the relation was created in this transaction, it will now be
+ * present in the pending-delete list twice, once with atCommit true and
+ * once with atCommit false. Hence, it will be physically deleted at end
+ * of xact in either case (and the other entry will be ignored by
+ * smgrDoPendingDeletes, so no error will occur). We could instead remove
+ * the existing list entry and delete the physical file immediately, but
+ * for now I'll keep the logic simple.
+ */
+
+ RelationCloseSmgr(rel);
+}
+
+/*
+ * RelationPreserveStorage
+ * Mark a relation as not to be deleted after all.
+ *
+ * We need this function because relation mapping changes are committed
+ * separately from commit of the whole transaction, so it's still possible
+ * for the transaction to abort after the mapping update is done.
+ * When a new physical relation is installed in the map, it would be
+ * scheduled for delete-on-abort, so we'd delete it, and be in trouble.
+ * The relation mapper fixes this by telling us to not delete such relations
+ * after all as part of its commit.
+ *
+ * We also use this to reuse an old build of an index during ALTER TABLE, this
+ * time removing the delete-at-commit entry.
+ *
+ * No-op if the relation is not among those scheduled for deletion.
+ */
+void
+RelationPreserveStorage(RelFileNode rnode, bool atCommit)
+{
+ PendingRelDelete *pending;
+ PendingRelDelete *prev;
+ PendingRelDelete *next;
+
+ prev = NULL;
+ for (pending = pendingDeletes; pending != NULL; pending = next)
+ {
+ next = pending->next;
+ if (RelFileNodeEquals(rnode, pending->relnode)
+ && pending->atCommit == atCommit)
+ {
+ /* unlink and delete list entry */
+ if (prev)
+ prev->next = next;
+ else
+ pendingDeletes = next;
+ pfree(pending);
+ /* prev does not change */
+ }
+ else
+ {
+ /* unrelated entry, don't touch it */
+ prev = pending;
+ }
+ }
+}
+
+/*
+ * RelationTruncate
+ * Physically truncate a relation to the specified number of blocks.
+ *
+ * This includes getting rid of any buffers for the blocks that are to be
+ * dropped.
+ */
+void
+RelationTruncate(Relation rel, BlockNumber nblocks)
+{
+ bool fsm;
+ bool vm;
+ bool need_fsm_vacuum = false;
+ ForkNumber forks[MAX_FORKNUM];
+ BlockNumber blocks[MAX_FORKNUM];
+ int nforks = 0;
+
+ /* Open it at the smgr level if not already done */
+ RelationOpenSmgr(rel);
+
+ /*
+ * Make sure smgr_targblock etc aren't pointing somewhere past new end
+ */
+ rel->rd_smgr->smgr_targblock = InvalidBlockNumber;
+ rel->rd_smgr->smgr_fsm_nblocks = InvalidBlockNumber;
+ rel->rd_smgr->smgr_vm_nblocks = InvalidBlockNumber;
+
+ /* Prepare for truncation of MAIN fork of the relation */
+ forks[nforks] = MAIN_FORKNUM;
+ blocks[nforks] = nblocks;
+ nforks++;
+
+ /* Prepare for truncation of the FSM if it exists */
+ fsm = smgrexists(rel->rd_smgr, FSM_FORKNUM);
+ if (fsm)
+ {
+ blocks[nforks] = FreeSpaceMapPrepareTruncateRel(rel, nblocks);
+ if (BlockNumberIsValid(blocks[nforks]))
+ {
+ forks[nforks] = FSM_FORKNUM;
+ nforks++;
+ need_fsm_vacuum = true;
+ }
+ }
+
+ /* Prepare for truncation of the visibility map too if it exists */
+ vm = smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
+ if (vm)
+ {
+ blocks[nforks] = visibilitymap_prepare_truncate(rel, nblocks);
+ if (BlockNumberIsValid(blocks[nforks]))
+ {
+ forks[nforks] = VISIBILITYMAP_FORKNUM;
+ nforks++;
+ }
+ }
+
+ RelationPreTruncate(rel);
+
+ /*
+ * We WAL-log the truncation before actually truncating, which means
+ * trouble if the truncation fails. If we then crash, the WAL replay
+ * likely isn't going to succeed in the truncation either, and cause a
+ * PANIC. It's tempting to put a critical section here, but that cure
+ * would be worse than the disease. It would turn a usually harmless
+ * failure to truncate, that might spell trouble at WAL replay, into a
+ * certain PANIC.
+ */
+ if (RelationNeedsWAL(rel))
+ {
+ /*
+ * Make an XLOG entry reporting the file truncation.
+ */
+ XLogRecPtr lsn;
+ xl_smgr_truncate xlrec;
+
+ xlrec.blkno = nblocks;
+ xlrec.rnode = rel->rd_node;
+ xlrec.flags = SMGR_TRUNCATE_ALL;
+
+ XLogBeginInsert();
+ XLogRegisterData((char *) &xlrec, sizeof(xlrec));
+
+ lsn = XLogInsert(RM_SMGR_ID,
+ XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
+
+ /*
+ * Flush, because otherwise the truncation of the main relation might
+ * hit the disk before the WAL record, and the truncation of the FSM
+ * or visibility map. If we crashed during that window, we'd be left
+ * with a truncated heap, but the FSM or visibility map would still
+ * contain entries for the non-existent heap pages.
+ */
+ if (fsm || vm)
+ XLogFlush(lsn);
+ }
+
+ /* Do the real work to truncate relation forks */
+ smgrtruncate(rel->rd_smgr, forks, nforks, blocks);
+
+ /*
+ * Update upper-level FSM pages to account for the truncation. This is
+ * important because the just-truncated pages were likely marked as
+ * all-free, and would be preferentially selected.
+ */
+ if (need_fsm_vacuum)
+ FreeSpaceMapVacuumRange(rel, nblocks, InvalidBlockNumber);
+}
+
+/*
+ * RelationPreTruncate
+ * Perform AM-independent work before a physical truncation.
+ *
+ * If an access method's relation_nontransactional_truncate does not call
+ * RelationTruncate(), it must call this before decreasing the table size.
+ */
+void
+RelationPreTruncate(Relation rel)
+{
+ PendingRelSync *pending;
+
+ if (!pendingSyncHash)
+ return;
+ RelationOpenSmgr(rel);
+
+ pending = hash_search(pendingSyncHash, &(rel->rd_smgr->smgr_rnode.node),
+ HASH_FIND, NULL);
+ if (pending)
+ pending->is_truncated = true;
+}
+
+/*
+ * Copy a fork's data, block by block.
+ *
+ * Note that this requires that there is no dirty data in shared buffers. If
+ * it's possible that there are, callers need to flush those using
+ * e.g. FlushRelationBuffers(rel).
+ */
+void
+RelationCopyStorage(SMgrRelation src, SMgrRelation dst,
+ ForkNumber forkNum, char relpersistence)
+{
+ PGAlignedBlock buf;
+ Page page;
+ bool use_wal;
+ bool copying_initfork;
+ BlockNumber nblocks;
+ BlockNumber blkno;
+
+ page = (Page) buf.data;
+
+ /*
+ * The init fork for an unlogged relation in many respects has to be
+ * treated the same as normal relation, changes need to be WAL logged and
+ * it needs to be synced to disk.
+ */
+ copying_initfork = relpersistence == RELPERSISTENCE_UNLOGGED &&
+ forkNum == INIT_FORKNUM;
+
+ /*
+ * We need to log the copied data in WAL iff WAL archiving/streaming is
+ * enabled AND it's a permanent relation. This gives the same answer as
+ * "RelationNeedsWAL(rel) || copying_initfork", because we know the
+ * current operation created a new relfilenode.
+ */
+ use_wal = XLogIsNeeded() &&
+ (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork);
+
+ nblocks = smgrnblocks(src, forkNum);
+
+ for (blkno = 0; blkno < nblocks; blkno++)
+ {
+ /* If we got a cancel signal during the copy of the data, quit */
+ CHECK_FOR_INTERRUPTS();
+
+ smgrread(src, forkNum, blkno, buf.data);
+
+ if (!PageIsVerifiedExtended(page, blkno,
+ PIV_LOG_WARNING | PIV_REPORT_STAT))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATA_CORRUPTED),
+ errmsg("invalid page in block %u of relation %s",
+ blkno,
+ relpathbackend(src->smgr_rnode.node,
+ src->smgr_rnode.backend,
+ forkNum))));
+
+ /*
+ * WAL-log the copied page. Unfortunately we don't know what kind of a
+ * page this is, so we have to log the full page including any unused
+ * space.
+ */
+ if (use_wal)
+ log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page, false);
+
+ PageSetChecksumInplace(page, blkno);
+
+ /*
+ * Now write the page. We say skipFsync = true because there's no
+ * need for smgr to schedule an fsync for this write; we'll do it
+ * ourselves below.
+ */
+ smgrextend(dst, forkNum, blkno, buf.data, true);
+ }
+
+ /*
+ * When we WAL-logged rel pages, we must nonetheless fsync them. The
+ * reason is that since we're copying outside shared buffers, a CHECKPOINT
+ * occurring during the copy has no way to flush the previously written
+ * data to disk (indeed it won't know the new rel even exists). A crash
+ * later on would replay WAL from the checkpoint, therefore it wouldn't
+ * replay our earlier WAL entries. If we do not fsync those pages here,
+ * they might still not be on disk when the crash occurs.
+ */
+ if (use_wal || copying_initfork)
+ smgrimmedsync(dst, forkNum);
+}
+
+/*
+ * RelFileNodeSkippingWAL
+ * Check if a BM_PERMANENT relfilenode is using WAL.
+ *
+ * Changes of certain relfilenodes must not write WAL; see "Skipping WAL for
+ * New RelFileNode" in src/backend/access/transam/README. Though it is known
+ * from Relation efficiently, this function is intended for the code paths not
+ * having access to Relation.
+ */
+bool
+RelFileNodeSkippingWAL(RelFileNode rnode)
+{
+ if (!pendingSyncHash ||
+ hash_search(pendingSyncHash, &rnode, HASH_FIND, NULL) == NULL)
+ return false;
+
+ return true;
+}
+
+/*
+ * EstimatePendingSyncsSpace
+ * Estimate space needed to pass syncs to parallel workers.
+ */
+Size
+EstimatePendingSyncsSpace(void)
+{
+ long entries;
+
+ entries = pendingSyncHash ? hash_get_num_entries(pendingSyncHash) : 0;
+ return mul_size(1 + entries, sizeof(RelFileNode));
+}
+
+/*
+ * SerializePendingSyncs
+ * Serialize syncs for parallel workers.
+ */
+void
+SerializePendingSyncs(Size maxSize, char *startAddress)
+{
+ HTAB *tmphash;
+ HASHCTL ctl;
+ HASH_SEQ_STATUS scan;
+ PendingRelSync *sync;
+ PendingRelDelete *delete;
+ RelFileNode *src;
+ RelFileNode *dest = (RelFileNode *) startAddress;
+
+ if (!pendingSyncHash)
+ goto terminate;
+
+ /* Create temporary hash to collect active relfilenodes */
+ ctl.keysize = sizeof(RelFileNode);
+ ctl.entrysize = sizeof(RelFileNode);
+ ctl.hcxt = CurrentMemoryContext;
+ tmphash = hash_create("tmp relfilenodes",
+ hash_get_num_entries(pendingSyncHash), &ctl,
+ HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+
+ /* collect all rnodes from pending syncs */
+ hash_seq_init(&scan, pendingSyncHash);
+ while ((sync = (PendingRelSync *) hash_seq_search(&scan)))
+ (void) hash_search(tmphash, &sync->rnode, HASH_ENTER, NULL);
+
+ /* remove deleted rnodes */
+ for (delete = pendingDeletes; delete != NULL; delete = delete->next)
+ if (delete->atCommit)
+ (void) hash_search(tmphash, (void *) &delete->relnode,
+ HASH_REMOVE, NULL);
+
+ hash_seq_init(&scan, tmphash);
+ while ((src = (RelFileNode *) hash_seq_search(&scan)))
+ *dest++ = *src;
+
+ hash_destroy(tmphash);
+
+terminate:
+ MemSet(dest, 0, sizeof(RelFileNode));
+}
+
+/*
+ * RestorePendingSyncs
+ * Restore syncs within a parallel worker.
+ *
+ * RelationNeedsWAL() and RelFileNodeSkippingWAL() must offer the correct
+ * answer to parallel workers. Only smgrDoPendingSyncs() reads the
+ * is_truncated field, at end of transaction. Hence, don't restore it.
+ */
+void
+RestorePendingSyncs(char *startAddress)
+{
+ RelFileNode *rnode;
+
+ Assert(pendingSyncHash == NULL);
+ for (rnode = (RelFileNode *) startAddress; rnode->relNode != 0; rnode++)
+ AddPendingSync(rnode);
+}
+
+/*
+ * smgrDoPendingDeletes() -- Take care of relation deletes at end of xact.
+ *
+ * This also runs when aborting a subxact; we want to clean up a failed
+ * subxact immediately.
+ *
+ * Note: It's possible that we're being asked to remove a relation that has
+ * no physical storage in any fork. In particular, it's possible that we're
+ * cleaning up an old temporary relation for which RemovePgTempFiles has
+ * already recovered the physical storage.
+ */
+void
+smgrDoPendingDeletes(bool isCommit)
+{
+ int nestLevel = GetCurrentTransactionNestLevel();
+ PendingRelDelete *pending;
+ PendingRelDelete *prev;
+ PendingRelDelete *next;
+ int nrels = 0,
+ i = 0,
+ maxrels = 0;
+ SMgrRelation *srels = NULL;
+
+ prev = NULL;
+ for (pending = pendingDeletes; pending != NULL; pending = next)
+ {
+ next = pending->next;
+ if (pending->nestLevel < nestLevel)
+ {
+ /* outer-level entries should not be processed yet */
+ prev = pending;
+ }
+ else
+ {
+ /* unlink list entry first, so we don't retry on failure */
+ if (prev)
+ prev->next = next;
+ else
+ pendingDeletes = next;
+ /* do deletion if called for */
+ if (pending->atCommit == isCommit)
+ {
+ SMgrRelation srel;
+
+ srel = smgropen(pending->relnode, pending->backend);
+
+ /* allocate the initial array, or extend it, if needed */
+ if (maxrels == 0)
+ {
+ maxrels = 8;
+ srels = palloc(sizeof(SMgrRelation) * maxrels);
+ }
+ else if (maxrels <= nrels)
+ {
+ maxrels *= 2;
+ srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
+ }
+
+ srels[nrels++] = srel;
+ }
+ /* must explicitly free the list entry */
+ pfree(pending);
+ /* prev does not change */
+ }
+ }
+
+ if (nrels > 0)
+ {
+ smgrdounlinkall(srels, nrels, false);
+
+ for (i = 0; i < nrels; i++)
+ smgrclose(srels[i]);
+
+ pfree(srels);
+ }
+}
+
+/*
+ * smgrDoPendingSyncs() -- Take care of relation syncs at end of xact.
+ */
+void
+smgrDoPendingSyncs(bool isCommit, bool isParallelWorker)
+{
+ PendingRelDelete *pending;
+ int nrels = 0,
+ maxrels = 0;
+ SMgrRelation *srels = NULL;
+ HASH_SEQ_STATUS scan;
+ PendingRelSync *pendingsync;
+
+ Assert(GetCurrentTransactionNestLevel() == 1);
+
+ if (!pendingSyncHash)
+ return; /* no relation needs sync */
+
+ /* Abort -- just throw away all pending syncs */
+ if (!isCommit)
+ {
+ pendingSyncHash = NULL;
+ return;
+ }
+
+ AssertPendingSyncs_RelationCache();
+
+ /* Parallel worker -- just throw away all pending syncs */
+ if (isParallelWorker)
+ {
+ pendingSyncHash = NULL;
+ return;
+ }
+
+ /* Skip syncing nodes that smgrDoPendingDeletes() will delete. */
+ for (pending = pendingDeletes; pending != NULL; pending = pending->next)
+ if (pending->atCommit)
+ (void) hash_search(pendingSyncHash, (void *) &pending->relnode,
+ HASH_REMOVE, NULL);
+
+ hash_seq_init(&scan, pendingSyncHash);
+ while ((pendingsync = (PendingRelSync *) hash_seq_search(&scan)))
+ {
+ ForkNumber fork;
+ BlockNumber nblocks[MAX_FORKNUM + 1];
+ BlockNumber total_blocks = 0;
+ SMgrRelation srel;
+
+ srel = smgropen(pendingsync->rnode, InvalidBackendId);
+
+ /*
+ * We emit newpage WAL records for smaller relations.
+ *
+ * Small WAL records have a chance to be emitted along with other
+ * backends' WAL records. We emit WAL records instead of syncing for
+ * files that are smaller than a certain threshold, expecting faster
+ * commit. The threshold is defined by the GUC wal_skip_threshold.
+ */
+ if (!pendingsync->is_truncated)
+ {
+ for (fork = 0; fork <= MAX_FORKNUM; fork++)
+ {
+ if (smgrexists(srel, fork))
+ {
+ BlockNumber n = smgrnblocks(srel, fork);
+
+ /* we shouldn't come here for unlogged relations */
+ Assert(fork != INIT_FORKNUM);
+ nblocks[fork] = n;
+ total_blocks += n;
+ }
+ else
+ nblocks[fork] = InvalidBlockNumber;
+ }
+ }
+
+ /*
+ * Sync file or emit WAL records for its contents.
+ *
+ * Although we emit WAL record if the file is small enough, do file
+ * sync regardless of the size if the file has experienced a
+ * truncation. It is because the file would be followed by trailing
+ * garbage blocks after a crash recovery if, while a past longer file
+ * had been flushed out, we omitted syncing-out of the file and
+ * emitted WAL instead. You might think that we could choose WAL if
+ * the current main fork is longer than ever, but there's a case where
+ * main fork is longer than ever but FSM fork gets shorter.
+ */
+ if (pendingsync->is_truncated ||
+ total_blocks * BLCKSZ / 1024 >= wal_skip_threshold)
+ {
+ /* allocate the initial array, or extend it, if needed */
+ if (maxrels == 0)
+ {
+ maxrels = 8;
+ srels = palloc(sizeof(SMgrRelation) * maxrels);
+ }
+ else if (maxrels <= nrels)
+ {
+ maxrels *= 2;
+ srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
+ }
+
+ srels[nrels++] = srel;
+ }
+ else
+ {
+ /* Emit WAL records for all blocks. The file is small enough. */
+ for (fork = 0; fork <= MAX_FORKNUM; fork++)
+ {
+ int n = nblocks[fork];
+ Relation rel;
+
+ if (!BlockNumberIsValid(n))
+ continue;
+
+ /*
+ * Emit WAL for the whole file. Unfortunately we don't know
+ * what kind of a page this is, so we have to log the full
+ * page including any unused space. ReadBufferExtended()
+ * counts some pgstat events; unfortunately, we discard them.
+ */
+ rel = CreateFakeRelcacheEntry(srel->smgr_rnode.node);
+ log_newpage_range(rel, fork, 0, n, false);
+ FreeFakeRelcacheEntry(rel);
+ }
+ }
+ }
+
+ pendingSyncHash = NULL;
+
+ if (nrels > 0)
+ {
+ smgrdosyncall(srels, nrels);
+ pfree(srels);
+ }
+}
+
+/*
+ * smgrGetPendingDeletes() -- Get a list of non-temp relations to be deleted.
+ *
+ * The return value is the number of relations scheduled for termination.
+ * *ptr is set to point to a freshly-palloc'd array of RelFileNodes.
+ * If there are no relations to be deleted, *ptr is set to NULL.
+ *
+ * Only non-temporary relations are included in the returned list. This is OK
+ * because the list is used only in contexts where temporary relations don't
+ * matter: we're either writing to the two-phase state file (and transactions
+ * that have touched temp tables can't be prepared) or we're writing to xlog
+ * (and all temporary files will be zapped if we restart anyway, so no need
+ * for redo to do it also).
+ *
+ * Note that the list does not include anything scheduled for termination
+ * by upper-level transactions.
+ */
+int
+smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr)
+{
+ int nestLevel = GetCurrentTransactionNestLevel();
+ int nrels;
+ RelFileNode *rptr;
+ PendingRelDelete *pending;
+
+ nrels = 0;
+ for (pending = pendingDeletes; pending != NULL; pending = pending->next)
+ {
+ if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
+ && pending->backend == InvalidBackendId)
+ nrels++;
+ }
+ if (nrels == 0)
+ {
+ *ptr = NULL;
+ return 0;
+ }
+ rptr = (RelFileNode *) palloc(nrels * sizeof(RelFileNode));
+ *ptr = rptr;
+ for (pending = pendingDeletes; pending != NULL; pending = pending->next)
+ {
+ if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
+ && pending->backend == InvalidBackendId)
+ {
+ *rptr = pending->relnode;
+ rptr++;
+ }
+ }
+ return nrels;
+}
+
+/*
+ * PostPrepare_smgr -- Clean up after a successful PREPARE
+ *
+ * What we have to do here is throw away the in-memory state about pending
+ * relation deletes. It's all been recorded in the 2PC state file and
+ * it's no longer smgr's job to worry about it.
+ */
+void
+PostPrepare_smgr(void)
+{
+ PendingRelDelete *pending;
+ PendingRelDelete *next;
+
+ for (pending = pendingDeletes; pending != NULL; pending = next)
+ {
+ next = pending->next;
+ pendingDeletes = next;
+ /* must explicitly free the list entry */
+ pfree(pending);
+ }
+}
+
+
+/*
+ * AtSubCommit_smgr() --- Take care of subtransaction commit.
+ *
+ * Reassign all items in the pending-deletes list to the parent transaction.
+ */
+void
+AtSubCommit_smgr(void)
+{
+ int nestLevel = GetCurrentTransactionNestLevel();
+ PendingRelDelete *pending;
+
+ for (pending = pendingDeletes; pending != NULL; pending = pending->next)
+ {
+ if (pending->nestLevel >= nestLevel)
+ pending->nestLevel = nestLevel - 1;
+ }
+}
+
+/*
+ * AtSubAbort_smgr() --- Take care of subtransaction abort.
+ *
+ * Delete created relations and forget about deleted relations.
+ * We can execute these operations immediately because we know this
+ * subtransaction will not commit.
+ */
+void
+AtSubAbort_smgr(void)
+{
+ smgrDoPendingDeletes(false);
+}
+
+void
+smgr_redo(XLogReaderState *record)
+{
+ XLogRecPtr lsn = record->EndRecPtr;
+ uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
+
+ /* Backup blocks are not used in smgr records */
+ Assert(!XLogRecHasAnyBlockRefs(record));
+
+ if (info == XLOG_SMGR_CREATE)
+ {
+ xl_smgr_create *xlrec = (xl_smgr_create *) XLogRecGetData(record);
+ SMgrRelation reln;
+
+ reln = smgropen(xlrec->rnode, InvalidBackendId);
+ smgrcreate(reln, xlrec->forkNum, true);
+ }
+ else if (info == XLOG_SMGR_TRUNCATE)
+ {
+ xl_smgr_truncate *xlrec = (xl_smgr_truncate *) XLogRecGetData(record);
+ SMgrRelation reln;
+ Relation rel;
+ ForkNumber forks[MAX_FORKNUM];
+ BlockNumber blocks[MAX_FORKNUM];
+ int nforks = 0;
+ bool need_fsm_vacuum = false;
+
+ reln = smgropen(xlrec->rnode, InvalidBackendId);
+
+ /*
+ * Forcibly create relation if it doesn't exist (which suggests that
+ * it was dropped somewhere later in the WAL sequence). As in
+ * XLogReadBufferForRedo, we prefer to recreate the rel and replay the
+ * log as best we can until the drop is seen.
+ */
+ smgrcreate(reln, MAIN_FORKNUM, true);
+
+ /*
+ * Before we perform the truncation, update minimum recovery point to
+ * cover this WAL record. Once the relation is truncated, there's no
+ * going back. The buffer manager enforces the WAL-first rule for
+ * normal updates to relation files, so that the minimum recovery
+ * point is always updated before the corresponding change in the data
+ * file is flushed to disk. We have to do the same manually here.
+ *
+ * Doing this before the truncation means that if the truncation fails
+ * for some reason, you cannot start up the system even after restart,
+ * until you fix the underlying situation so that the truncation will
+ * succeed. Alternatively, we could update the minimum recovery point
+ * after truncation, but that would leave a small window where the
+ * WAL-first rule could be violated.
+ */
+ XLogFlush(lsn);
+
+ /* Prepare for truncation of MAIN fork */
+ if ((xlrec->flags & SMGR_TRUNCATE_HEAP) != 0)
+ {
+ forks[nforks] = MAIN_FORKNUM;
+ blocks[nforks] = xlrec->blkno;
+ nforks++;
+
+ /* Also tell xlogutils.c about it */
+ XLogTruncateRelation(xlrec->rnode, MAIN_FORKNUM, xlrec->blkno);
+ }
+
+ /* Prepare for truncation of FSM and VM too */
+ rel = CreateFakeRelcacheEntry(xlrec->rnode);
+
+ if ((xlrec->flags & SMGR_TRUNCATE_FSM) != 0 &&
+ smgrexists(reln, FSM_FORKNUM))
+ {
+ blocks[nforks] = FreeSpaceMapPrepareTruncateRel(rel, xlrec->blkno);
+ if (BlockNumberIsValid(blocks[nforks]))
+ {
+ forks[nforks] = FSM_FORKNUM;
+ nforks++;
+ need_fsm_vacuum = true;
+ }
+ }
+ if ((xlrec->flags & SMGR_TRUNCATE_VM) != 0 &&
+ smgrexists(reln, VISIBILITYMAP_FORKNUM))
+ {
+ blocks[nforks] = visibilitymap_prepare_truncate(rel, xlrec->blkno);
+ if (BlockNumberIsValid(blocks[nforks]))
+ {
+ forks[nforks] = VISIBILITYMAP_FORKNUM;
+ nforks++;
+ }
+ }
+
+ /* Do the real work to truncate relation forks */
+ if (nforks > 0)
+ smgrtruncate(reln, forks, nforks, blocks);
+
+ /*
+ * Update upper-level FSM pages to account for the truncation. This is
+ * important because the just-truncated pages were likely marked as
+ * all-free, and would be preferentially selected.
+ */
+ if (need_fsm_vacuum)
+ FreeSpaceMapVacuumRange(rel, xlrec->blkno,
+ InvalidBlockNumber);
+
+ FreeFakeRelcacheEntry(rel);
+ }
+ else
+ elog(PANIC, "smgr_redo: unknown op code %u", info);
+}
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
new file mode 100644
index 0000000..51d738c
--- /dev/null
+++ b/src/backend/catalog/system_views.sql
@@ -0,0 +1,1480 @@
+/*
+ * PostgreSQL System Views
+ *
+ * Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ * src/backend/catalog/system_views.sql
+ *
+ * Note: this file is read in single-user -j mode, which means that the
+ * command terminator is semicolon-newline-newline; whenever the backend
+ * sees that, it stops and executes what it's got. If you write a lot of
+ * statements without empty lines between, they'll all get quoted to you
+ * in any error message about one of them, so don't do that. Also, you
+ * cannot write a semicolon immediately followed by an empty line in a
+ * string literal (including a function body!) or a multiline comment.
+ */
+
+CREATE VIEW pg_roles AS
+ SELECT
+ rolname,
+ rolsuper,
+ rolinherit,
+ rolcreaterole,
+ rolcreatedb,
+ rolcanlogin,
+ rolreplication,
+ rolconnlimit,
+ '********'::text as rolpassword,
+ rolvaliduntil,
+ rolbypassrls,
+ setconfig as rolconfig,
+ pg_authid.oid
+ FROM pg_authid LEFT JOIN pg_db_role_setting s
+ ON (pg_authid.oid = setrole AND setdatabase = 0);
+
+CREATE VIEW pg_shadow AS
+ SELECT
+ rolname AS usename,
+ pg_authid.oid AS usesysid,
+ rolcreatedb AS usecreatedb,
+ rolsuper AS usesuper,
+ rolreplication AS userepl,
+ rolbypassrls AS usebypassrls,
+ rolpassword AS passwd,
+ rolvaliduntil AS valuntil,
+ setconfig AS useconfig
+ FROM pg_authid LEFT JOIN pg_db_role_setting s
+ ON (pg_authid.oid = setrole AND setdatabase = 0)
+ WHERE rolcanlogin;
+
+REVOKE ALL on pg_shadow FROM public;
+
+CREATE VIEW pg_group AS
+ SELECT
+ rolname AS groname,
+ oid AS grosysid,
+ ARRAY(SELECT member FROM pg_auth_members WHERE roleid = oid) AS grolist
+ FROM pg_authid
+ WHERE NOT rolcanlogin;
+
+CREATE VIEW pg_user AS
+ SELECT
+ usename,
+ usesysid,
+ usecreatedb,
+ usesuper,
+ userepl,
+ usebypassrls,
+ '********'::text as passwd,
+ valuntil,
+ useconfig
+ FROM pg_shadow;
+
+CREATE VIEW pg_policies AS
+ SELECT
+ N.nspname AS schemaname,
+ C.relname AS tablename,
+ pol.polname AS policyname,
+ CASE
+ WHEN pol.polpermissive THEN
+ 'PERMISSIVE'
+ ELSE
+ 'RESTRICTIVE'
+ END AS permissive,
+ CASE
+ WHEN pol.polroles = '{0}' THEN
+ string_to_array('public', '')
+ ELSE
+ ARRAY
+ (
+ SELECT rolname
+ FROM pg_catalog.pg_authid
+ WHERE oid = ANY (pol.polroles) ORDER BY 1
+ )
+ END AS roles,
+ CASE pol.polcmd
+ WHEN 'r' THEN 'SELECT'
+ WHEN 'a' THEN 'INSERT'
+ WHEN 'w' THEN 'UPDATE'
+ WHEN 'd' THEN 'DELETE'
+ WHEN '*' THEN 'ALL'
+ END AS cmd,
+ pg_catalog.pg_get_expr(pol.polqual, pol.polrelid) AS qual,
+ pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid) AS with_check
+ FROM pg_catalog.pg_policy pol
+ JOIN pg_catalog.pg_class C ON (C.oid = pol.polrelid)
+ LEFT JOIN pg_catalog.pg_namespace N ON (N.oid = C.relnamespace);
+
+CREATE VIEW pg_rules AS
+ SELECT
+ N.nspname AS schemaname,
+ C.relname AS tablename,
+ R.rulename AS rulename,
+ pg_get_ruledef(R.oid) AS definition
+ FROM (pg_rewrite R JOIN pg_class C ON (C.oid = R.ev_class))
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE R.rulename != '_RETURN';
+
+CREATE VIEW pg_views AS
+ SELECT
+ N.nspname AS schemaname,
+ C.relname AS viewname,
+ pg_get_userbyid(C.relowner) AS viewowner,
+ pg_get_viewdef(C.oid) AS definition
+ FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE C.relkind = 'v';
+
+CREATE VIEW pg_tables AS
+ SELECT
+ N.nspname AS schemaname,
+ C.relname AS tablename,
+ pg_get_userbyid(C.relowner) AS tableowner,
+ T.spcname AS tablespace,
+ C.relhasindex AS hasindexes,
+ C.relhasrules AS hasrules,
+ C.relhastriggers AS hastriggers,
+ C.relrowsecurity AS rowsecurity
+ FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ LEFT JOIN pg_tablespace T ON (T.oid = C.reltablespace)
+ WHERE C.relkind IN ('r', 'p');
+
+CREATE VIEW pg_matviews AS
+ SELECT
+ N.nspname AS schemaname,
+ C.relname AS matviewname,
+ pg_get_userbyid(C.relowner) AS matviewowner,
+ T.spcname AS tablespace,
+ C.relhasindex AS hasindexes,
+ C.relispopulated AS ispopulated,
+ pg_get_viewdef(C.oid) AS definition
+ FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ LEFT JOIN pg_tablespace T ON (T.oid = C.reltablespace)
+ WHERE C.relkind = 'm';
+
+CREATE VIEW pg_indexes AS
+ SELECT
+ N.nspname AS schemaname,
+ C.relname AS tablename,
+ I.relname AS indexname,
+ T.spcname AS tablespace,
+ pg_get_indexdef(I.oid) AS indexdef
+ FROM pg_index X JOIN pg_class C ON (C.oid = X.indrelid)
+ JOIN pg_class I ON (I.oid = X.indexrelid)
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ LEFT JOIN pg_tablespace T ON (T.oid = I.reltablespace)
+ WHERE C.relkind IN ('r', 'm', 'p') AND I.relkind IN ('i', 'I');
+
+CREATE OR REPLACE VIEW pg_sequences AS
+ SELECT
+ N.nspname AS schemaname,
+ C.relname AS sequencename,
+ pg_get_userbyid(C.relowner) AS sequenceowner,
+ S.seqtypid::regtype AS data_type,
+ S.seqstart AS start_value,
+ S.seqmin AS min_value,
+ S.seqmax AS max_value,
+ S.seqincrement AS increment_by,
+ S.seqcycle AS cycle,
+ S.seqcache AS cache_size,
+ CASE
+ WHEN has_sequence_privilege(C.oid, 'SELECT,USAGE'::text)
+ THEN pg_sequence_last_value(C.oid)
+ ELSE NULL
+ END AS last_value
+ FROM pg_sequence S JOIN pg_class C ON (C.oid = S.seqrelid)
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE NOT pg_is_other_temp_schema(N.oid)
+ AND relkind = 'S';
+
+CREATE VIEW pg_stats WITH (security_barrier) AS
+ SELECT
+ nspname AS schemaname,
+ relname AS tablename,
+ attname AS attname,
+ stainherit AS inherited,
+ stanullfrac AS null_frac,
+ stawidth AS avg_width,
+ stadistinct AS n_distinct,
+ CASE
+ WHEN stakind1 = 1 THEN stavalues1
+ WHEN stakind2 = 1 THEN stavalues2
+ WHEN stakind3 = 1 THEN stavalues3
+ WHEN stakind4 = 1 THEN stavalues4
+ WHEN stakind5 = 1 THEN stavalues5
+ END AS most_common_vals,
+ CASE
+ WHEN stakind1 = 1 THEN stanumbers1
+ WHEN stakind2 = 1 THEN stanumbers2
+ WHEN stakind3 = 1 THEN stanumbers3
+ WHEN stakind4 = 1 THEN stanumbers4
+ WHEN stakind5 = 1 THEN stanumbers5
+ END AS most_common_freqs,
+ CASE
+ WHEN stakind1 = 2 THEN stavalues1
+ WHEN stakind2 = 2 THEN stavalues2
+ WHEN stakind3 = 2 THEN stavalues3
+ WHEN stakind4 = 2 THEN stavalues4
+ WHEN stakind5 = 2 THEN stavalues5
+ END AS histogram_bounds,
+ CASE
+ WHEN stakind1 = 3 THEN stanumbers1[1]
+ WHEN stakind2 = 3 THEN stanumbers2[1]
+ WHEN stakind3 = 3 THEN stanumbers3[1]
+ WHEN stakind4 = 3 THEN stanumbers4[1]
+ WHEN stakind5 = 3 THEN stanumbers5[1]
+ END AS correlation,
+ CASE
+ WHEN stakind1 = 4 THEN stavalues1
+ WHEN stakind2 = 4 THEN stavalues2
+ WHEN stakind3 = 4 THEN stavalues3
+ WHEN stakind4 = 4 THEN stavalues4
+ WHEN stakind5 = 4 THEN stavalues5
+ END AS most_common_elems,
+ CASE
+ WHEN stakind1 = 4 THEN stanumbers1
+ WHEN stakind2 = 4 THEN stanumbers2
+ WHEN stakind3 = 4 THEN stanumbers3
+ WHEN stakind4 = 4 THEN stanumbers4
+ WHEN stakind5 = 4 THEN stanumbers5
+ END AS most_common_elem_freqs,
+ CASE
+ WHEN stakind1 = 5 THEN stanumbers1
+ WHEN stakind2 = 5 THEN stanumbers2
+ WHEN stakind3 = 5 THEN stanumbers3
+ WHEN stakind4 = 5 THEN stanumbers4
+ WHEN stakind5 = 5 THEN stanumbers5
+ END AS elem_count_histogram
+ FROM pg_statistic s JOIN pg_class c ON (c.oid = s.starelid)
+ JOIN pg_attribute a ON (c.oid = attrelid AND attnum = s.staattnum)
+ LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)
+ WHERE NOT attisdropped
+ AND has_column_privilege(c.oid, a.attnum, 'select')
+ AND (c.relrowsecurity = false OR NOT row_security_active(c.oid));
+
+REVOKE ALL on pg_statistic FROM public;
+
+CREATE VIEW pg_stats_ext WITH (security_barrier) AS
+ SELECT cn.nspname AS schemaname,
+ c.relname AS tablename,
+ sn.nspname AS statistics_schemaname,
+ s.stxname AS statistics_name,
+ pg_get_userbyid(s.stxowner) AS statistics_owner,
+ ( SELECT array_agg(a.attname ORDER BY a.attnum)
+ FROM unnest(s.stxkeys) k
+ JOIN pg_attribute a
+ ON (a.attrelid = s.stxrelid AND a.attnum = k)
+ ) AS attnames,
+ s.stxkind AS kinds,
+ sd.stxdndistinct AS n_distinct,
+ sd.stxddependencies AS dependencies,
+ m.most_common_vals,
+ m.most_common_val_nulls,
+ m.most_common_freqs,
+ m.most_common_base_freqs
+ FROM pg_statistic_ext s JOIN pg_class c ON (c.oid = s.stxrelid)
+ JOIN pg_statistic_ext_data sd ON (s.oid = sd.stxoid)
+ LEFT JOIN pg_namespace cn ON (cn.oid = c.relnamespace)
+ LEFT JOIN pg_namespace sn ON (sn.oid = s.stxnamespace)
+ LEFT JOIN LATERAL
+ ( SELECT array_agg(values) AS most_common_vals,
+ array_agg(nulls) AS most_common_val_nulls,
+ array_agg(frequency) AS most_common_freqs,
+ array_agg(base_frequency) AS most_common_base_freqs
+ FROM pg_mcv_list_items(sd.stxdmcv)
+ ) m ON sd.stxdmcv IS NOT NULL
+ WHERE NOT EXISTS
+ ( SELECT 1
+ FROM unnest(stxkeys) k
+ JOIN pg_attribute a
+ ON (a.attrelid = s.stxrelid AND a.attnum = k)
+ WHERE NOT has_column_privilege(c.oid, a.attnum, 'select') )
+ AND (c.relrowsecurity = false OR NOT row_security_active(c.oid));
+
+-- unprivileged users may read pg_statistic_ext but not pg_statistic_ext_data
+REVOKE ALL on pg_statistic_ext_data FROM public;
+
+CREATE VIEW pg_publication_tables AS
+ SELECT
+ P.pubname AS pubname,
+ N.nspname AS schemaname,
+ C.relname AS tablename
+ FROM pg_publication P,
+ LATERAL pg_get_publication_tables(P.pubname) GPT,
+ pg_class C JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE C.oid = GPT.relid;
+
+CREATE VIEW pg_locks AS
+ SELECT * FROM pg_lock_status() AS L;
+
+CREATE VIEW pg_cursors AS
+ SELECT * FROM pg_cursor() AS C;
+
+CREATE VIEW pg_available_extensions AS
+ SELECT E.name, E.default_version, X.extversion AS installed_version,
+ E.comment
+ FROM pg_available_extensions() AS E
+ LEFT JOIN pg_extension AS X ON E.name = X.extname;
+
+CREATE VIEW pg_available_extension_versions AS
+ SELECT E.name, E.version, (X.extname IS NOT NULL) AS installed,
+ E.superuser, E.trusted, E.relocatable,
+ E.schema, E.requires, E.comment
+ FROM pg_available_extension_versions() AS E
+ LEFT JOIN pg_extension AS X
+ ON E.name = X.extname AND E.version = X.extversion;
+
+CREATE VIEW pg_prepared_xacts AS
+ SELECT P.transaction, P.gid, P.prepared,
+ U.rolname AS owner, D.datname AS database
+ FROM pg_prepared_xact() AS P
+ LEFT JOIN pg_authid U ON P.ownerid = U.oid
+ LEFT JOIN pg_database D ON P.dbid = D.oid;
+
+CREATE VIEW pg_prepared_statements AS
+ SELECT * FROM pg_prepared_statement() AS P;
+
+CREATE VIEW pg_seclabels AS
+SELECT
+ l.objoid, l.classoid, l.objsubid,
+ CASE WHEN rel.relkind IN ('r', 'p') THEN 'table'::text
+ WHEN rel.relkind = 'v' THEN 'view'::text
+ WHEN rel.relkind = 'm' THEN 'materialized view'::text
+ WHEN rel.relkind = 'S' THEN 'sequence'::text
+ WHEN rel.relkind = 'f' THEN 'foreign table'::text END AS objtype,
+ rel.relnamespace AS objnamespace,
+ CASE WHEN pg_table_is_visible(rel.oid)
+ THEN quote_ident(rel.relname)
+ ELSE quote_ident(nsp.nspname) || '.' || quote_ident(rel.relname)
+ END AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_class rel ON l.classoid = rel.tableoid AND l.objoid = rel.oid
+ JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
+WHERE
+ l.objsubid = 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, l.objsubid,
+ 'column'::text AS objtype,
+ rel.relnamespace AS objnamespace,
+ CASE WHEN pg_table_is_visible(rel.oid)
+ THEN quote_ident(rel.relname)
+ ELSE quote_ident(nsp.nspname) || '.' || quote_ident(rel.relname)
+ END || '.' || att.attname AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_class rel ON l.classoid = rel.tableoid AND l.objoid = rel.oid
+ JOIN pg_attribute att
+ ON rel.oid = att.attrelid AND l.objsubid = att.attnum
+ JOIN pg_namespace nsp ON rel.relnamespace = nsp.oid
+WHERE
+ l.objsubid != 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, l.objsubid,
+ CASE pro.prokind
+ WHEN 'a' THEN 'aggregate'::text
+ WHEN 'f' THEN 'function'::text
+ WHEN 'p' THEN 'procedure'::text
+ WHEN 'w' THEN 'window'::text END AS objtype,
+ pro.pronamespace AS objnamespace,
+ CASE WHEN pg_function_is_visible(pro.oid)
+ THEN quote_ident(pro.proname)
+ ELSE quote_ident(nsp.nspname) || '.' || quote_ident(pro.proname)
+ END || '(' || pg_catalog.pg_get_function_arguments(pro.oid) || ')' AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_proc pro ON l.classoid = pro.tableoid AND l.objoid = pro.oid
+ JOIN pg_namespace nsp ON pro.pronamespace = nsp.oid
+WHERE
+ l.objsubid = 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, l.objsubid,
+ CASE WHEN typ.typtype = 'd' THEN 'domain'::text
+ ELSE 'type'::text END AS objtype,
+ typ.typnamespace AS objnamespace,
+ CASE WHEN pg_type_is_visible(typ.oid)
+ THEN quote_ident(typ.typname)
+ ELSE quote_ident(nsp.nspname) || '.' || quote_ident(typ.typname)
+ END AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_type typ ON l.classoid = typ.tableoid AND l.objoid = typ.oid
+ JOIN pg_namespace nsp ON typ.typnamespace = nsp.oid
+WHERE
+ l.objsubid = 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, l.objsubid,
+ 'large object'::text AS objtype,
+ NULL::oid AS objnamespace,
+ l.objoid::text AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_largeobject_metadata lom ON l.objoid = lom.oid
+WHERE
+ l.classoid = 'pg_catalog.pg_largeobject'::regclass AND l.objsubid = 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, l.objsubid,
+ 'language'::text AS objtype,
+ NULL::oid AS objnamespace,
+ quote_ident(lan.lanname) AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_language lan ON l.classoid = lan.tableoid AND l.objoid = lan.oid
+WHERE
+ l.objsubid = 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, l.objsubid,
+ 'schema'::text AS objtype,
+ nsp.oid AS objnamespace,
+ quote_ident(nsp.nspname) AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_namespace nsp ON l.classoid = nsp.tableoid AND l.objoid = nsp.oid
+WHERE
+ l.objsubid = 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, l.objsubid,
+ 'event trigger'::text AS objtype,
+ NULL::oid AS objnamespace,
+ quote_ident(evt.evtname) AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_event_trigger evt ON l.classoid = evt.tableoid
+ AND l.objoid = evt.oid
+WHERE
+ l.objsubid = 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, l.objsubid,
+ 'publication'::text AS objtype,
+ NULL::oid AS objnamespace,
+ quote_ident(p.pubname) AS objname,
+ l.provider, l.label
+FROM
+ pg_seclabel l
+ JOIN pg_publication p ON l.classoid = p.tableoid AND l.objoid = p.oid
+WHERE
+ l.objsubid = 0
+UNION ALL
+SELECT
+ l.objoid, l.classoid, 0::int4 AS objsubid,
+ 'subscription'::text AS objtype,
+ NULL::oid AS objnamespace,
+ quote_ident(s.subname) AS objname,
+ l.provider, l.label
+FROM
+ pg_shseclabel l
+ JOIN pg_subscription s ON l.classoid = s.tableoid AND l.objoid = s.oid
+UNION ALL
+SELECT
+ l.objoid, l.classoid, 0::int4 AS objsubid,
+ 'database'::text AS objtype,
+ NULL::oid AS objnamespace,
+ quote_ident(dat.datname) AS objname,
+ l.provider, l.label
+FROM
+ pg_shseclabel l
+ JOIN pg_database dat ON l.classoid = dat.tableoid AND l.objoid = dat.oid
+UNION ALL
+SELECT
+ l.objoid, l.classoid, 0::int4 AS objsubid,
+ 'tablespace'::text AS objtype,
+ NULL::oid AS objnamespace,
+ quote_ident(spc.spcname) AS objname,
+ l.provider, l.label
+FROM
+ pg_shseclabel l
+ JOIN pg_tablespace spc ON l.classoid = spc.tableoid AND l.objoid = spc.oid
+UNION ALL
+SELECT
+ l.objoid, l.classoid, 0::int4 AS objsubid,
+ 'role'::text AS objtype,
+ NULL::oid AS objnamespace,
+ quote_ident(rol.rolname) AS objname,
+ l.provider, l.label
+FROM
+ pg_shseclabel l
+ JOIN pg_authid rol ON l.classoid = rol.tableoid AND l.objoid = rol.oid;
+
+CREATE VIEW pg_settings AS
+ SELECT * FROM pg_show_all_settings() AS A;
+
+CREATE RULE pg_settings_u AS
+ ON UPDATE TO pg_settings
+ WHERE new.name = old.name DO
+ SELECT set_config(old.name, new.setting, 'f');
+
+CREATE RULE pg_settings_n AS
+ ON UPDATE TO pg_settings
+ DO INSTEAD NOTHING;
+
+GRANT SELECT, UPDATE ON pg_settings TO PUBLIC;
+
+CREATE VIEW pg_file_settings AS
+ SELECT * FROM pg_show_all_file_settings() AS A;
+
+REVOKE ALL on pg_file_settings FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pg_show_all_file_settings() FROM PUBLIC;
+
+CREATE VIEW pg_hba_file_rules AS
+ SELECT * FROM pg_hba_file_rules() AS A;
+
+REVOKE ALL on pg_hba_file_rules FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pg_hba_file_rules() FROM PUBLIC;
+
+CREATE VIEW pg_timezone_abbrevs AS
+ SELECT * FROM pg_timezone_abbrevs();
+
+CREATE VIEW pg_timezone_names AS
+ SELECT * FROM pg_timezone_names();
+
+CREATE VIEW pg_config AS
+ SELECT * FROM pg_config();
+
+REVOKE ALL on pg_config FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pg_config() FROM PUBLIC;
+
+CREATE VIEW pg_shmem_allocations AS
+ SELECT * FROM pg_get_shmem_allocations();
+
+REVOKE ALL ON pg_shmem_allocations FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pg_get_shmem_allocations() FROM PUBLIC;
+
+-- Statistics views
+
+CREATE VIEW pg_stat_all_tables AS
+ SELECT
+ C.oid AS relid,
+ N.nspname AS schemaname,
+ C.relname AS relname,
+ pg_stat_get_numscans(C.oid) AS seq_scan,
+ pg_stat_get_tuples_returned(C.oid) AS seq_tup_read,
+ sum(pg_stat_get_numscans(I.indexrelid))::bigint AS idx_scan,
+ sum(pg_stat_get_tuples_fetched(I.indexrelid))::bigint +
+ pg_stat_get_tuples_fetched(C.oid) AS idx_tup_fetch,
+ pg_stat_get_tuples_inserted(C.oid) AS n_tup_ins,
+ pg_stat_get_tuples_updated(C.oid) AS n_tup_upd,
+ pg_stat_get_tuples_deleted(C.oid) AS n_tup_del,
+ pg_stat_get_tuples_hot_updated(C.oid) AS n_tup_hot_upd,
+ pg_stat_get_live_tuples(C.oid) AS n_live_tup,
+ pg_stat_get_dead_tuples(C.oid) AS n_dead_tup,
+ pg_stat_get_mod_since_analyze(C.oid) AS n_mod_since_analyze,
+ pg_stat_get_ins_since_vacuum(C.oid) AS n_ins_since_vacuum,
+ pg_stat_get_last_vacuum_time(C.oid) as last_vacuum,
+ pg_stat_get_last_autovacuum_time(C.oid) as last_autovacuum,
+ pg_stat_get_last_analyze_time(C.oid) as last_analyze,
+ pg_stat_get_last_autoanalyze_time(C.oid) as last_autoanalyze,
+ pg_stat_get_vacuum_count(C.oid) AS vacuum_count,
+ pg_stat_get_autovacuum_count(C.oid) AS autovacuum_count,
+ pg_stat_get_analyze_count(C.oid) AS analyze_count,
+ pg_stat_get_autoanalyze_count(C.oid) AS autoanalyze_count
+ FROM pg_class C LEFT JOIN
+ pg_index I ON C.oid = I.indrelid
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE C.relkind IN ('r', 't', 'm')
+ GROUP BY C.oid, N.nspname, C.relname;
+
+CREATE VIEW pg_stat_xact_all_tables AS
+ SELECT
+ C.oid AS relid,
+ N.nspname AS schemaname,
+ C.relname AS relname,
+ pg_stat_get_xact_numscans(C.oid) AS seq_scan,
+ pg_stat_get_xact_tuples_returned(C.oid) AS seq_tup_read,
+ sum(pg_stat_get_xact_numscans(I.indexrelid))::bigint AS idx_scan,
+ sum(pg_stat_get_xact_tuples_fetched(I.indexrelid))::bigint +
+ pg_stat_get_xact_tuples_fetched(C.oid) AS idx_tup_fetch,
+ pg_stat_get_xact_tuples_inserted(C.oid) AS n_tup_ins,
+ pg_stat_get_xact_tuples_updated(C.oid) AS n_tup_upd,
+ pg_stat_get_xact_tuples_deleted(C.oid) AS n_tup_del,
+ pg_stat_get_xact_tuples_hot_updated(C.oid) AS n_tup_hot_upd
+ FROM pg_class C LEFT JOIN
+ pg_index I ON C.oid = I.indrelid
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE C.relkind IN ('r', 't', 'm')
+ GROUP BY C.oid, N.nspname, C.relname;
+
+CREATE VIEW pg_stat_sys_tables AS
+ SELECT * FROM pg_stat_all_tables
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
+
+CREATE VIEW pg_stat_xact_sys_tables AS
+ SELECT * FROM pg_stat_xact_all_tables
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
+
+CREATE VIEW pg_stat_user_tables AS
+ SELECT * FROM pg_stat_all_tables
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
+
+CREATE VIEW pg_stat_xact_user_tables AS
+ SELECT * FROM pg_stat_xact_all_tables
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
+
+CREATE VIEW pg_statio_all_tables AS
+ SELECT
+ C.oid AS relid,
+ N.nspname AS schemaname,
+ C.relname AS relname,
+ pg_stat_get_blocks_fetched(C.oid) -
+ pg_stat_get_blocks_hit(C.oid) AS heap_blks_read,
+ pg_stat_get_blocks_hit(C.oid) AS heap_blks_hit,
+ sum(pg_stat_get_blocks_fetched(I.indexrelid) -
+ pg_stat_get_blocks_hit(I.indexrelid))::bigint AS idx_blks_read,
+ sum(pg_stat_get_blocks_hit(I.indexrelid))::bigint AS idx_blks_hit,
+ pg_stat_get_blocks_fetched(T.oid) -
+ pg_stat_get_blocks_hit(T.oid) AS toast_blks_read,
+ pg_stat_get_blocks_hit(T.oid) AS toast_blks_hit,
+ pg_stat_get_blocks_fetched(X.indexrelid) -
+ pg_stat_get_blocks_hit(X.indexrelid) AS tidx_blks_read,
+ pg_stat_get_blocks_hit(X.indexrelid) AS tidx_blks_hit
+ FROM pg_class C LEFT JOIN
+ pg_index I ON C.oid = I.indrelid LEFT JOIN
+ pg_class T ON C.reltoastrelid = T.oid LEFT JOIN
+ pg_index X ON T.oid = X.indrelid
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE C.relkind IN ('r', 't', 'm')
+ GROUP BY C.oid, N.nspname, C.relname, T.oid, X.indexrelid;
+
+CREATE VIEW pg_statio_sys_tables AS
+ SELECT * FROM pg_statio_all_tables
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
+
+CREATE VIEW pg_statio_user_tables AS
+ SELECT * FROM pg_statio_all_tables
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
+
+CREATE VIEW pg_stat_all_indexes AS
+ SELECT
+ C.oid AS relid,
+ I.oid AS indexrelid,
+ N.nspname AS schemaname,
+ C.relname AS relname,
+ I.relname AS indexrelname,
+ pg_stat_get_numscans(I.oid) AS idx_scan,
+ pg_stat_get_tuples_returned(I.oid) AS idx_tup_read,
+ pg_stat_get_tuples_fetched(I.oid) AS idx_tup_fetch
+ FROM pg_class C JOIN
+ pg_index X ON C.oid = X.indrelid JOIN
+ pg_class I ON I.oid = X.indexrelid
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE C.relkind IN ('r', 't', 'm');
+
+CREATE VIEW pg_stat_sys_indexes AS
+ SELECT * FROM pg_stat_all_indexes
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
+
+CREATE VIEW pg_stat_user_indexes AS
+ SELECT * FROM pg_stat_all_indexes
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
+
+CREATE VIEW pg_statio_all_indexes AS
+ SELECT
+ C.oid AS relid,
+ I.oid AS indexrelid,
+ N.nspname AS schemaname,
+ C.relname AS relname,
+ I.relname AS indexrelname,
+ pg_stat_get_blocks_fetched(I.oid) -
+ pg_stat_get_blocks_hit(I.oid) AS idx_blks_read,
+ pg_stat_get_blocks_hit(I.oid) AS idx_blks_hit
+ FROM pg_class C JOIN
+ pg_index X ON C.oid = X.indrelid JOIN
+ pg_class I ON I.oid = X.indexrelid
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE C.relkind IN ('r', 't', 'm');
+
+CREATE VIEW pg_statio_sys_indexes AS
+ SELECT * FROM pg_statio_all_indexes
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
+
+CREATE VIEW pg_statio_user_indexes AS
+ SELECT * FROM pg_statio_all_indexes
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
+
+CREATE VIEW pg_statio_all_sequences AS
+ SELECT
+ C.oid AS relid,
+ N.nspname AS schemaname,
+ C.relname AS relname,
+ pg_stat_get_blocks_fetched(C.oid) -
+ pg_stat_get_blocks_hit(C.oid) AS blks_read,
+ pg_stat_get_blocks_hit(C.oid) AS blks_hit
+ FROM pg_class C
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE C.relkind = 'S';
+
+CREATE VIEW pg_statio_sys_sequences AS
+ SELECT * FROM pg_statio_all_sequences
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
+
+CREATE VIEW pg_statio_user_sequences AS
+ SELECT * FROM pg_statio_all_sequences
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
+
+CREATE VIEW pg_stat_activity AS
+ SELECT
+ S.datid AS datid,
+ D.datname AS datname,
+ S.pid,
+ S.leader_pid,
+ S.usesysid,
+ U.rolname AS usename,
+ S.application_name,
+ S.client_addr,
+ S.client_hostname,
+ S.client_port,
+ S.backend_start,
+ S.xact_start,
+ S.query_start,
+ S.state_change,
+ S.wait_event_type,
+ S.wait_event,
+ S.state,
+ S.backend_xid,
+ s.backend_xmin,
+ S.query,
+ S.backend_type
+ FROM pg_stat_get_activity(NULL) AS S
+ LEFT JOIN pg_database AS D ON (S.datid = D.oid)
+ LEFT JOIN pg_authid AS U ON (S.usesysid = U.oid);
+
+CREATE VIEW pg_stat_replication AS
+ SELECT
+ S.pid,
+ S.usesysid,
+ U.rolname AS usename,
+ S.application_name,
+ S.client_addr,
+ S.client_hostname,
+ S.client_port,
+ S.backend_start,
+ S.backend_xmin,
+ W.state,
+ W.sent_lsn,
+ W.write_lsn,
+ W.flush_lsn,
+ W.replay_lsn,
+ W.write_lag,
+ W.flush_lag,
+ W.replay_lag,
+ W.sync_priority,
+ W.sync_state,
+ W.reply_time
+ FROM pg_stat_get_activity(NULL) AS S
+ JOIN pg_stat_get_wal_senders() AS W ON (S.pid = W.pid)
+ LEFT JOIN pg_authid AS U ON (S.usesysid = U.oid);
+
+CREATE VIEW pg_stat_slru AS
+ SELECT
+ s.name,
+ s.blks_zeroed,
+ s.blks_hit,
+ s.blks_read,
+ s.blks_written,
+ s.blks_exists,
+ s.flushes,
+ s.truncates,
+ s.stats_reset
+ FROM pg_stat_get_slru() s;
+
+CREATE VIEW pg_stat_wal_receiver AS
+ SELECT
+ s.pid,
+ s.status,
+ s.receive_start_lsn,
+ s.receive_start_tli,
+ s.written_lsn,
+ s.flushed_lsn,
+ s.received_tli,
+ s.last_msg_send_time,
+ s.last_msg_receipt_time,
+ s.latest_end_lsn,
+ s.latest_end_time,
+ s.slot_name,
+ s.sender_host,
+ s.sender_port,
+ s.conninfo
+ FROM pg_stat_get_wal_receiver() s
+ WHERE s.pid IS NOT NULL;
+
+CREATE VIEW pg_stat_subscription AS
+ SELECT
+ su.oid AS subid,
+ su.subname,
+ st.pid,
+ st.relid,
+ st.received_lsn,
+ st.last_msg_send_time,
+ st.last_msg_receipt_time,
+ st.latest_end_lsn,
+ st.latest_end_time
+ FROM pg_subscription su
+ LEFT JOIN pg_stat_get_subscription(NULL) st
+ ON (st.subid = su.oid);
+
+CREATE VIEW pg_stat_ssl AS
+ SELECT
+ S.pid,
+ S.ssl,
+ S.sslversion AS version,
+ S.sslcipher AS cipher,
+ S.sslbits AS bits,
+ S.sslcompression AS compression,
+ S.ssl_client_dn AS client_dn,
+ S.ssl_client_serial AS client_serial,
+ S.ssl_issuer_dn AS issuer_dn
+ FROM pg_stat_get_activity(NULL) AS S
+ WHERE S.client_port IS NOT NULL;
+
+CREATE VIEW pg_stat_gssapi AS
+ SELECT
+ S.pid,
+ S.gss_auth AS gss_authenticated,
+ S.gss_princ AS principal,
+ S.gss_enc AS encrypted
+ FROM pg_stat_get_activity(NULL) AS S
+ WHERE S.client_port IS NOT NULL;
+
+CREATE VIEW pg_replication_slots AS
+ SELECT
+ L.slot_name,
+ L.plugin,
+ L.slot_type,
+ L.datoid,
+ D.datname AS database,
+ L.temporary,
+ L.active,
+ L.active_pid,
+ L.xmin,
+ L.catalog_xmin,
+ L.restart_lsn,
+ L.confirmed_flush_lsn,
+ L.wal_status,
+ L.safe_wal_size
+ FROM pg_get_replication_slots() AS L
+ LEFT JOIN pg_database D ON (L.datoid = D.oid);
+
+CREATE VIEW pg_stat_database AS
+ SELECT
+ D.oid AS datid,
+ D.datname AS datname,
+ CASE
+ WHEN (D.oid = (0)::oid) THEN 0
+ ELSE pg_stat_get_db_numbackends(D.oid)
+ END AS numbackends,
+ pg_stat_get_db_xact_commit(D.oid) AS xact_commit,
+ pg_stat_get_db_xact_rollback(D.oid) AS xact_rollback,
+ pg_stat_get_db_blocks_fetched(D.oid) -
+ pg_stat_get_db_blocks_hit(D.oid) AS blks_read,
+ pg_stat_get_db_blocks_hit(D.oid) AS blks_hit,
+ pg_stat_get_db_tuples_returned(D.oid) AS tup_returned,
+ pg_stat_get_db_tuples_fetched(D.oid) AS tup_fetched,
+ pg_stat_get_db_tuples_inserted(D.oid) AS tup_inserted,
+ pg_stat_get_db_tuples_updated(D.oid) AS tup_updated,
+ pg_stat_get_db_tuples_deleted(D.oid) AS tup_deleted,
+ pg_stat_get_db_conflict_all(D.oid) AS conflicts,
+ pg_stat_get_db_temp_files(D.oid) AS temp_files,
+ pg_stat_get_db_temp_bytes(D.oid) AS temp_bytes,
+ pg_stat_get_db_deadlocks(D.oid) AS deadlocks,
+ pg_stat_get_db_checksum_failures(D.oid) AS checksum_failures,
+ pg_stat_get_db_checksum_last_failure(D.oid) AS checksum_last_failure,
+ pg_stat_get_db_blk_read_time(D.oid) AS blk_read_time,
+ pg_stat_get_db_blk_write_time(D.oid) AS blk_write_time,
+ pg_stat_get_db_stat_reset_time(D.oid) AS stats_reset
+ FROM (
+ SELECT 0 AS oid, NULL::name AS datname
+ UNION ALL
+ SELECT oid, datname FROM pg_database
+ ) D;
+
+CREATE VIEW pg_stat_database_conflicts AS
+ SELECT
+ D.oid AS datid,
+ D.datname AS datname,
+ pg_stat_get_db_conflict_tablespace(D.oid) AS confl_tablespace,
+ pg_stat_get_db_conflict_lock(D.oid) AS confl_lock,
+ pg_stat_get_db_conflict_snapshot(D.oid) AS confl_snapshot,
+ pg_stat_get_db_conflict_bufferpin(D.oid) AS confl_bufferpin,
+ pg_stat_get_db_conflict_startup_deadlock(D.oid) AS confl_deadlock
+ FROM pg_database D;
+
+CREATE VIEW pg_stat_user_functions AS
+ SELECT
+ P.oid AS funcid,
+ N.nspname AS schemaname,
+ P.proname AS funcname,
+ pg_stat_get_function_calls(P.oid) AS calls,
+ pg_stat_get_function_total_time(P.oid) AS total_time,
+ pg_stat_get_function_self_time(P.oid) AS self_time
+ FROM pg_proc P LEFT JOIN pg_namespace N ON (N.oid = P.pronamespace)
+ WHERE P.prolang != 12 -- fast check to eliminate built-in functions
+ AND pg_stat_get_function_calls(P.oid) IS NOT NULL;
+
+CREATE VIEW pg_stat_xact_user_functions AS
+ SELECT
+ P.oid AS funcid,
+ N.nspname AS schemaname,
+ P.proname AS funcname,
+ pg_stat_get_xact_function_calls(P.oid) AS calls,
+ pg_stat_get_xact_function_total_time(P.oid) AS total_time,
+ pg_stat_get_xact_function_self_time(P.oid) AS self_time
+ FROM pg_proc P LEFT JOIN pg_namespace N ON (N.oid = P.pronamespace)
+ WHERE P.prolang != 12 -- fast check to eliminate built-in functions
+ AND pg_stat_get_xact_function_calls(P.oid) IS NOT NULL;
+
+CREATE VIEW pg_stat_archiver AS
+ SELECT
+ s.archived_count,
+ s.last_archived_wal,
+ s.last_archived_time,
+ s.failed_count,
+ s.last_failed_wal,
+ s.last_failed_time,
+ s.stats_reset
+ FROM pg_stat_get_archiver() s;
+
+CREATE VIEW pg_stat_bgwriter AS
+ SELECT
+ pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed,
+ pg_stat_get_bgwriter_requested_checkpoints() AS checkpoints_req,
+ pg_stat_get_checkpoint_write_time() AS checkpoint_write_time,
+ pg_stat_get_checkpoint_sync_time() AS checkpoint_sync_time,
+ pg_stat_get_bgwriter_buf_written_checkpoints() AS buffers_checkpoint,
+ pg_stat_get_bgwriter_buf_written_clean() AS buffers_clean,
+ pg_stat_get_bgwriter_maxwritten_clean() AS maxwritten_clean,
+ pg_stat_get_buf_written_backend() AS buffers_backend,
+ pg_stat_get_buf_fsync_backend() AS buffers_backend_fsync,
+ pg_stat_get_buf_alloc() AS buffers_alloc,
+ pg_stat_get_bgwriter_stat_reset_time() AS stats_reset;
+
+CREATE VIEW pg_stat_progress_analyze AS
+ SELECT
+ S.pid AS pid, S.datid AS datid, D.datname AS datname,
+ CAST(S.relid AS oid) AS relid,
+ CASE S.param1 WHEN 0 THEN 'initializing'
+ WHEN 1 THEN 'acquiring sample rows'
+ WHEN 2 THEN 'acquiring inherited sample rows'
+ WHEN 3 THEN 'computing statistics'
+ WHEN 4 THEN 'computing extended statistics'
+ WHEN 5 THEN 'finalizing analyze'
+ END AS phase,
+ S.param2 AS sample_blks_total,
+ S.param3 AS sample_blks_scanned,
+ S.param4 AS ext_stats_total,
+ S.param5 AS ext_stats_computed,
+ S.param6 AS child_tables_total,
+ S.param7 AS child_tables_done,
+ CAST(S.param8 AS oid) AS current_child_table_relid
+ FROM pg_stat_get_progress_info('ANALYZE') AS S
+ LEFT JOIN pg_database D ON S.datid = D.oid;
+
+CREATE VIEW pg_stat_progress_vacuum AS
+ SELECT
+ S.pid AS pid, S.datid AS datid, D.datname AS datname,
+ S.relid AS relid,
+ CASE S.param1 WHEN 0 THEN 'initializing'
+ WHEN 1 THEN 'scanning heap'
+ WHEN 2 THEN 'vacuuming indexes'
+ WHEN 3 THEN 'vacuuming heap'
+ WHEN 4 THEN 'cleaning up indexes'
+ WHEN 5 THEN 'truncating heap'
+ WHEN 6 THEN 'performing final cleanup'
+ END AS phase,
+ S.param2 AS heap_blks_total, S.param3 AS heap_blks_scanned,
+ S.param4 AS heap_blks_vacuumed, S.param5 AS index_vacuum_count,
+ S.param6 AS max_dead_tuples, S.param7 AS num_dead_tuples
+ FROM pg_stat_get_progress_info('VACUUM') AS S
+ LEFT JOIN pg_database D ON S.datid = D.oid;
+
+CREATE VIEW pg_stat_progress_cluster AS
+ SELECT
+ S.pid AS pid,
+ S.datid AS datid,
+ D.datname AS datname,
+ S.relid AS relid,
+ CASE S.param1 WHEN 1 THEN 'CLUSTER'
+ WHEN 2 THEN 'VACUUM FULL'
+ END AS command,
+ CASE S.param2 WHEN 0 THEN 'initializing'
+ WHEN 1 THEN 'seq scanning heap'
+ WHEN 2 THEN 'index scanning heap'
+ WHEN 3 THEN 'sorting tuples'
+ WHEN 4 THEN 'writing new heap'
+ WHEN 5 THEN 'swapping relation files'
+ WHEN 6 THEN 'rebuilding index'
+ WHEN 7 THEN 'performing final cleanup'
+ END AS phase,
+ CAST(S.param3 AS oid) AS cluster_index_relid,
+ S.param4 AS heap_tuples_scanned,
+ S.param5 AS heap_tuples_written,
+ S.param6 AS heap_blks_total,
+ S.param7 AS heap_blks_scanned,
+ S.param8 AS index_rebuild_count
+ FROM pg_stat_get_progress_info('CLUSTER') AS S
+ LEFT JOIN pg_database D ON S.datid = D.oid;
+
+CREATE VIEW pg_stat_progress_create_index AS
+ SELECT
+ S.pid AS pid, S.datid AS datid, D.datname AS datname,
+ S.relid AS relid,
+ CAST(S.param7 AS oid) AS index_relid,
+ CASE S.param1 WHEN 1 THEN 'CREATE INDEX'
+ WHEN 2 THEN 'CREATE INDEX CONCURRENTLY'
+ WHEN 3 THEN 'REINDEX'
+ WHEN 4 THEN 'REINDEX CONCURRENTLY'
+ END AS command,
+ CASE S.param10 WHEN 0 THEN 'initializing'
+ WHEN 1 THEN 'waiting for writers before build'
+ WHEN 2 THEN 'building index' ||
+ COALESCE((': ' || pg_indexam_progress_phasename(S.param9::oid, S.param11)),
+ '')
+ WHEN 3 THEN 'waiting for writers before validation'
+ WHEN 4 THEN 'index validation: scanning index'
+ WHEN 5 THEN 'index validation: sorting tuples'
+ WHEN 6 THEN 'index validation: scanning table'
+ WHEN 7 THEN 'waiting for old snapshots'
+ WHEN 8 THEN 'waiting for readers before marking dead'
+ WHEN 9 THEN 'waiting for readers before dropping'
+ END as phase,
+ S.param4 AS lockers_total,
+ S.param5 AS lockers_done,
+ S.param6 AS current_locker_pid,
+ S.param16 AS blocks_total,
+ S.param17 AS blocks_done,
+ S.param12 AS tuples_total,
+ S.param13 AS tuples_done,
+ S.param14 AS partitions_total,
+ S.param15 AS partitions_done
+ FROM pg_stat_get_progress_info('CREATE INDEX') AS S
+ LEFT JOIN pg_database D ON S.datid = D.oid;
+
+CREATE VIEW pg_stat_progress_basebackup AS
+ SELECT
+ S.pid AS pid,
+ CASE S.param1 WHEN 0 THEN 'initializing'
+ WHEN 1 THEN 'waiting for checkpoint to finish'
+ WHEN 2 THEN 'estimating backup size'
+ WHEN 3 THEN 'streaming database files'
+ WHEN 4 THEN 'waiting for wal archiving to finish'
+ WHEN 5 THEN 'transferring wal files'
+ END AS phase,
+ CASE S.param2 WHEN -1 THEN NULL ELSE S.param2 END AS backup_total,
+ S.param3 AS backup_streamed,
+ S.param4 AS tablespaces_total,
+ S.param5 AS tablespaces_streamed
+ FROM pg_stat_get_progress_info('BASEBACKUP') AS S;
+
+CREATE VIEW pg_user_mappings AS
+ SELECT
+ U.oid AS umid,
+ S.oid AS srvid,
+ S.srvname AS srvname,
+ U.umuser AS umuser,
+ CASE WHEN U.umuser = 0 THEN
+ 'public'
+ ELSE
+ A.rolname
+ END AS usename,
+ CASE WHEN (U.umuser <> 0 AND A.rolname = current_user
+ AND (pg_has_role(S.srvowner, 'USAGE')
+ OR has_server_privilege(S.oid, 'USAGE')))
+ OR (U.umuser = 0 AND pg_has_role(S.srvowner, 'USAGE'))
+ OR (SELECT rolsuper FROM pg_authid WHERE rolname = current_user)
+ THEN U.umoptions
+ ELSE NULL END AS umoptions
+ FROM pg_user_mapping U
+ JOIN pg_foreign_server S ON (U.umserver = S.oid)
+ LEFT JOIN pg_authid A ON (A.oid = U.umuser);
+
+REVOKE ALL on pg_user_mapping FROM public;
+
+CREATE VIEW pg_replication_origin_status AS
+ SELECT *
+ FROM pg_show_replication_origin_status();
+
+REVOKE ALL ON pg_replication_origin_status FROM public;
+
+-- All columns of pg_subscription except subconninfo are readable.
+REVOKE ALL ON pg_subscription FROM public;
+GRANT SELECT (subdbid, subname, subowner, subenabled, subslotname, subpublications)
+ ON pg_subscription TO public;
+
+
+--
+-- We have a few function definitions in here, too.
+-- At some point there might be enough to justify breaking them out into
+-- a separate "system_functions.sql" file.
+--
+
+-- Tsearch debug function. Defined here because it'd be pretty unwieldy
+-- to put it into pg_proc.h
+
+CREATE FUNCTION ts_debug(IN config regconfig, IN document text,
+ OUT alias text,
+ OUT description text,
+ OUT token text,
+ OUT dictionaries regdictionary[],
+ OUT dictionary regdictionary,
+ OUT lexemes text[])
+RETURNS SETOF record AS
+$$
+SELECT
+ tt.alias AS alias,
+ tt.description AS description,
+ parse.token AS token,
+ ARRAY ( SELECT m.mapdict::pg_catalog.regdictionary
+ FROM pg_catalog.pg_ts_config_map AS m
+ WHERE m.mapcfg = $1 AND m.maptokentype = parse.tokid
+ ORDER BY m.mapseqno )
+ AS dictionaries,
+ ( SELECT mapdict::pg_catalog.regdictionary
+ FROM pg_catalog.pg_ts_config_map AS m
+ WHERE m.mapcfg = $1 AND m.maptokentype = parse.tokid
+ ORDER BY pg_catalog.ts_lexize(mapdict, parse.token) IS NULL, m.mapseqno
+ LIMIT 1
+ ) AS dictionary,
+ ( SELECT pg_catalog.ts_lexize(mapdict, parse.token)
+ FROM pg_catalog.pg_ts_config_map AS m
+ WHERE m.mapcfg = $1 AND m.maptokentype = parse.tokid
+ ORDER BY pg_catalog.ts_lexize(mapdict, parse.token) IS NULL, m.mapseqno
+ LIMIT 1
+ ) AS lexemes
+FROM pg_catalog.ts_parse(
+ (SELECT cfgparser FROM pg_catalog.pg_ts_config WHERE oid = $1 ), $2
+ ) AS parse,
+ pg_catalog.ts_token_type(
+ (SELECT cfgparser FROM pg_catalog.pg_ts_config WHERE oid = $1 )
+ ) AS tt
+WHERE tt.tokid = parse.tokid
+$$
+LANGUAGE SQL STRICT STABLE PARALLEL SAFE;
+
+COMMENT ON FUNCTION ts_debug(regconfig,text) IS
+ 'debug function for text search configuration';
+
+CREATE FUNCTION ts_debug(IN document text,
+ OUT alias text,
+ OUT description text,
+ OUT token text,
+ OUT dictionaries regdictionary[],
+ OUT dictionary regdictionary,
+ OUT lexemes text[])
+RETURNS SETOF record AS
+$$
+ SELECT * FROM pg_catalog.ts_debug( pg_catalog.get_current_ts_config(), $1);
+$$
+LANGUAGE SQL STRICT STABLE PARALLEL SAFE;
+
+COMMENT ON FUNCTION ts_debug(text) IS
+ 'debug function for current text search configuration';
+
+--
+-- Redeclare built-in functions that need default values attached to their
+-- arguments. It's impractical to set those up directly in pg_proc.h because
+-- of the complexity and platform-dependency of the expression tree
+-- representation. (Note that internal functions still have to have entries
+-- in pg_proc.h; we are merely causing their proargnames and proargdefaults
+-- to get filled in.)
+--
+
+CREATE OR REPLACE FUNCTION
+ pg_start_backup(label text, fast boolean DEFAULT false, exclusive boolean DEFAULT true)
+ RETURNS pg_lsn STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup'
+ PARALLEL RESTRICTED;
+
+CREATE OR REPLACE FUNCTION pg_stop_backup (
+ exclusive boolean, wait_for_archive boolean DEFAULT true,
+ OUT lsn pg_lsn, OUT labelfile text, OUT spcmapfile text)
+ RETURNS SETOF record STRICT VOLATILE LANGUAGE internal as 'pg_stop_backup_v2'
+ PARALLEL RESTRICTED;
+
+CREATE OR REPLACE FUNCTION
+ pg_promote(wait boolean DEFAULT true, wait_seconds integer DEFAULT 60)
+ RETURNS boolean STRICT VOLATILE LANGUAGE INTERNAL AS 'pg_promote'
+ PARALLEL SAFE;
+
+-- legacy definition for compatibility with 9.3
+CREATE OR REPLACE FUNCTION
+ json_populate_record(base anyelement, from_json json, use_json_as_text boolean DEFAULT false)
+ RETURNS anyelement LANGUAGE internal STABLE AS 'json_populate_record' PARALLEL SAFE;
+
+-- legacy definition for compatibility with 9.3
+CREATE OR REPLACE FUNCTION
+ json_populate_recordset(base anyelement, from_json json, use_json_as_text boolean DEFAULT false)
+ RETURNS SETOF anyelement LANGUAGE internal STABLE ROWS 100 AS 'json_populate_recordset' PARALLEL SAFE;
+
+CREATE OR REPLACE FUNCTION pg_logical_slot_get_changes(
+ IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
+ OUT lsn pg_lsn, OUT xid xid, OUT data text)
+RETURNS SETOF RECORD
+LANGUAGE INTERNAL
+VOLATILE ROWS 1000 COST 1000
+AS 'pg_logical_slot_get_changes';
+
+CREATE OR REPLACE FUNCTION pg_logical_slot_peek_changes(
+ IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
+ OUT lsn pg_lsn, OUT xid xid, OUT data text)
+RETURNS SETOF RECORD
+LANGUAGE INTERNAL
+VOLATILE ROWS 1000 COST 1000
+AS 'pg_logical_slot_peek_changes';
+
+CREATE OR REPLACE FUNCTION pg_logical_slot_get_binary_changes(
+ IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
+ OUT lsn pg_lsn, OUT xid xid, OUT data bytea)
+RETURNS SETOF RECORD
+LANGUAGE INTERNAL
+VOLATILE ROWS 1000 COST 1000
+AS 'pg_logical_slot_get_binary_changes';
+
+CREATE OR REPLACE FUNCTION pg_logical_slot_peek_binary_changes(
+ IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
+ OUT lsn pg_lsn, OUT xid xid, OUT data bytea)
+RETURNS SETOF RECORD
+LANGUAGE INTERNAL
+VOLATILE ROWS 1000 COST 1000
+AS 'pg_logical_slot_peek_binary_changes';
+
+CREATE OR REPLACE FUNCTION pg_create_physical_replication_slot(
+ IN slot_name name, IN immediately_reserve boolean DEFAULT false,
+ IN temporary boolean DEFAULT false,
+ OUT slot_name name, OUT lsn pg_lsn)
+RETURNS RECORD
+LANGUAGE INTERNAL
+STRICT VOLATILE
+AS 'pg_create_physical_replication_slot';
+
+CREATE OR REPLACE FUNCTION pg_create_logical_replication_slot(
+ IN slot_name name, IN plugin name,
+ IN temporary boolean DEFAULT false,
+ OUT slot_name name, OUT lsn pg_lsn)
+RETURNS RECORD
+LANGUAGE INTERNAL
+STRICT VOLATILE
+AS 'pg_create_logical_replication_slot';
+
+CREATE OR REPLACE FUNCTION
+ make_interval(years int4 DEFAULT 0, months int4 DEFAULT 0, weeks int4 DEFAULT 0,
+ days int4 DEFAULT 0, hours int4 DEFAULT 0, mins int4 DEFAULT 0,
+ secs double precision DEFAULT 0.0)
+RETURNS interval
+LANGUAGE INTERNAL
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'make_interval';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_set(jsonb_in jsonb, path text[] , replacement jsonb,
+ create_if_missing boolean DEFAULT true)
+RETURNS jsonb
+LANGUAGE INTERNAL
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'jsonb_set';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_set_lax(jsonb_in jsonb, path text[] , replacement jsonb,
+ create_if_missing boolean DEFAULT true,
+ null_value_treatment text DEFAULT 'use_json_null')
+RETURNS jsonb
+LANGUAGE INTERNAL
+CALLED ON NULL INPUT IMMUTABLE PARALLEL SAFE
+AS 'jsonb_set_lax';
+
+CREATE OR REPLACE FUNCTION
+ parse_ident(str text, strict boolean DEFAULT true)
+RETURNS text[]
+LANGUAGE INTERNAL
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'parse_ident';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_insert(jsonb_in jsonb, path text[] , replacement jsonb,
+ insert_after boolean DEFAULT false)
+RETURNS jsonb
+LANGUAGE INTERNAL
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'jsonb_insert';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_exists(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS boolean
+LANGUAGE INTERNAL
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'jsonb_path_exists';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_match(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS boolean
+LANGUAGE INTERNAL
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'jsonb_path_match';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_query(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS SETOF jsonb
+LANGUAGE INTERNAL
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'jsonb_path_query';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_query_array(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS jsonb
+LANGUAGE INTERNAL
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'jsonb_path_query_array';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_query_first(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS jsonb
+LANGUAGE INTERNAL
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'jsonb_path_query_first';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_exists_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS boolean
+LANGUAGE INTERNAL
+STRICT STABLE PARALLEL SAFE
+AS 'jsonb_path_exists_tz';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_match_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS boolean
+LANGUAGE INTERNAL
+STRICT STABLE PARALLEL SAFE
+AS 'jsonb_path_match_tz';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_query_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS SETOF jsonb
+LANGUAGE INTERNAL
+STRICT STABLE PARALLEL SAFE
+AS 'jsonb_path_query_tz';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_query_array_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS jsonb
+LANGUAGE INTERNAL
+STRICT STABLE PARALLEL SAFE
+AS 'jsonb_path_query_array_tz';
+
+CREATE OR REPLACE FUNCTION
+ jsonb_path_query_first_tz(target jsonb, path jsonpath, vars jsonb DEFAULT '{}',
+ silent boolean DEFAULT false)
+RETURNS jsonb
+LANGUAGE INTERNAL
+STRICT STABLE PARALLEL SAFE
+AS 'jsonb_path_query_first_tz';
+
+-- default normalization form is NFC, per SQL standard
+CREATE OR REPLACE FUNCTION
+ "normalize"(text, text DEFAULT 'NFC')
+RETURNS text
+LANGUAGE internal
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'unicode_normalize_func';
+
+CREATE OR REPLACE FUNCTION
+ is_normalized(text, text DEFAULT 'NFC')
+RETURNS boolean
+LANGUAGE internal
+STRICT IMMUTABLE PARALLEL SAFE
+AS 'unicode_is_normalized';
+
+--
+-- The default permissions for functions mean that anyone can execute them.
+-- A number of functions shouldn't be executable by just anyone, but rather
+-- than use explicit 'superuser()' checks in those functions, we use the GRANT
+-- system to REVOKE access to those functions at initdb time. Administrators
+-- can later change who can access these functions, or leave them as only
+-- available to superuser / cluster owner, if they choose.
+--
+REVOKE EXECUTE ON FUNCTION pg_start_backup(text, boolean, boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stop_backup() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stop_backup(boolean, boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_create_restore_point(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_switch_wal() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_wal_replay_pause() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_wal_replay_resume() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_rotate_logfile() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_reload_conf() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_current_logfile() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_current_logfile(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_promote(boolean, integer) FROM public;
+
+REVOKE EXECUTE ON FUNCTION pg_stat_reset() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stat_reset_shared(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stat_reset_slru(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_table_counters(oid) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_function_counters(oid) FROM public;
+
+REVOKE EXECUTE ON FUNCTION lo_import(text) FROM public;
+REVOKE EXECUTE ON FUNCTION lo_import(text, oid) FROM public;
+REVOKE EXECUTE ON FUNCTION lo_export(oid, text) FROM public;
+
+REVOKE EXECUTE ON FUNCTION pg_ls_logdir() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_waldir() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_archive_statusdir() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir(oid) FROM public;
+
+REVOKE EXECUTE ON FUNCTION pg_read_file(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_read_file(text,bigint,bigint) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_read_file(text,bigint,bigint,boolean) FROM public;
+
+REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text,bigint,bigint) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text,bigint,bigint,boolean) FROM public;
+
+REVOKE EXECUTE ON FUNCTION pg_stat_file(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stat_file(text,boolean) FROM public;
+
+REVOKE EXECUTE ON FUNCTION pg_ls_dir(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_dir(text,boolean,boolean) FROM public;
+
+--
+-- We also set up some things as accessible to standard roles.
+--
+GRANT EXECUTE ON FUNCTION pg_ls_logdir() TO pg_monitor;
+GRANT EXECUTE ON FUNCTION pg_ls_waldir() TO pg_monitor;
+GRANT EXECUTE ON FUNCTION pg_ls_archive_statusdir() TO pg_monitor;
+GRANT EXECUTE ON FUNCTION pg_ls_tmpdir() TO pg_monitor;
+GRANT EXECUTE ON FUNCTION pg_ls_tmpdir(oid) TO pg_monitor;
+
+GRANT pg_read_all_settings TO pg_monitor;
+GRANT pg_read_all_stats TO pg_monitor;
+GRANT pg_stat_scan_tables TO pg_monitor;
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
new file mode 100644
index 0000000..3f7ab8d
--- /dev/null
+++ b/src/backend/catalog/toasting.c
@@ -0,0 +1,418 @@
+/*-------------------------------------------------------------------------
+ *
+ * toasting.c
+ * This file contains routines to support creation of toast tables
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/catalog/toasting.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "access/xact.h"
+#include "catalog/binary_upgrade.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/heap.h"
+#include "catalog/index.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_type.h"
+#include "catalog/toasting.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "storage/lock.h"
+#include "utils/builtins.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+/* Potentially set by pg_upgrade_support functions */
+Oid binary_upgrade_next_toast_pg_type_oid = InvalidOid;
+
+static void CheckAndCreateToastTable(Oid relOid, Datum reloptions,
+ LOCKMODE lockmode, bool check);
+static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
+ Datum reloptions, LOCKMODE lockmode, bool check);
+static bool needs_toast_table(Relation rel);
+
+
+/*
+ * CreateToastTable variants
+ * If the table needs a toast table, and doesn't already have one,
+ * then create a toast table for it.
+ *
+ * reloptions for the toast table can be passed, too. Pass (Datum) 0
+ * for default reloptions.
+ *
+ * We expect the caller to have verified that the relation is a table and have
+ * already done any necessary permission checks. Callers expect this function
+ * to end with CommandCounterIncrement if it makes any changes.
+ */
+void
+AlterTableCreateToastTable(Oid relOid, Datum reloptions, LOCKMODE lockmode)
+{
+ CheckAndCreateToastTable(relOid, reloptions, lockmode, true);
+}
+
+void
+NewHeapCreateToastTable(Oid relOid, Datum reloptions, LOCKMODE lockmode)
+{
+ CheckAndCreateToastTable(relOid, reloptions, lockmode, false);
+}
+
+void
+NewRelationCreateToastTable(Oid relOid, Datum reloptions)
+{
+ CheckAndCreateToastTable(relOid, reloptions, AccessExclusiveLock, false);
+}
+
+static void
+CheckAndCreateToastTable(Oid relOid, Datum reloptions, LOCKMODE lockmode, bool check)
+{
+ Relation rel;
+
+ rel = table_open(relOid, lockmode);
+
+ /* create_toast_table does all the work */
+ (void) create_toast_table(rel, InvalidOid, InvalidOid, reloptions, lockmode, check);
+
+ table_close(rel, NoLock);
+}
+
+/*
+ * Create a toast table during bootstrap
+ *
+ * Here we need to prespecify the OIDs of the toast table and its index
+ */
+void
+BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
+{
+ Relation rel;
+
+ rel = table_openrv(makeRangeVar(NULL, relName, -1), AccessExclusiveLock);
+
+ if (rel->rd_rel->relkind != RELKIND_RELATION &&
+ rel->rd_rel->relkind != RELKIND_MATVIEW)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a table or materialized view",
+ relName)));
+
+ /* create_toast_table does all the work */
+ if (!create_toast_table(rel, toastOid, toastIndexOid, (Datum) 0,
+ AccessExclusiveLock, false))
+ elog(ERROR, "\"%s\" does not require a toast table",
+ relName);
+
+ table_close(rel, NoLock);
+}
+
+
+/*
+ * create_toast_table --- internal workhorse
+ *
+ * rel is already opened and locked
+ * toastOid and toastIndexOid are normally InvalidOid, but during
+ * bootstrap they can be nonzero to specify hand-assigned OIDs
+ */
+static bool
+create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
+ Datum reloptions, LOCKMODE lockmode, bool check)
+{
+ Oid relOid = RelationGetRelid(rel);
+ HeapTuple reltup;
+ TupleDesc tupdesc;
+ bool shared_relation;
+ bool mapped_relation;
+ Relation toast_rel;
+ Relation class_rel;
+ Oid toast_relid;
+ Oid toast_typid = InvalidOid;
+ Oid namespaceid;
+ char toast_relname[NAMEDATALEN];
+ char toast_idxname[NAMEDATALEN];
+ IndexInfo *indexInfo;
+ Oid collationObjectId[2];
+ Oid classObjectId[2];
+ int16 coloptions[2];
+ ObjectAddress baseobject,
+ toastobject;
+
+ /*
+ * Is it already toasted?
+ */
+ if (rel->rd_rel->reltoastrelid != InvalidOid)
+ return false;
+
+ /*
+ * Check to see whether the table actually needs a TOAST table.
+ */
+ if (!IsBinaryUpgrade)
+ {
+ /* Normal mode, normal check */
+ if (!needs_toast_table(rel))
+ return false;
+ }
+ else
+ {
+ /*
+ * In binary-upgrade mode, create a TOAST table if and only if
+ * pg_upgrade told us to (ie, a TOAST table OID has been provided).
+ *
+ * This indicates that the old cluster had a TOAST table for the
+ * current table. We must create a TOAST table to receive the old
+ * TOAST file, even if the table seems not to need one.
+ *
+ * Contrariwise, if the old cluster did not have a TOAST table, we
+ * should be able to get along without one even if the new version's
+ * needs_toast_table rules suggest we should have one. There is a lot
+ * of daylight between where we will create a TOAST table and where
+ * one is really necessary to avoid failures, so small cross-version
+ * differences in the when-to-create heuristic shouldn't be a problem.
+ * If we tried to create a TOAST table anyway, we would have the
+ * problem that it might take up an OID that will conflict with some
+ * old-cluster table we haven't seen yet.
+ */
+ if (!OidIsValid(binary_upgrade_next_toast_pg_class_oid) ||
+ !OidIsValid(binary_upgrade_next_toast_pg_type_oid))
+ return false;
+ }
+
+ /*
+ * If requested check lockmode is sufficient. This is a cross check in
+ * case of errors or conflicting decisions in earlier code.
+ */
+ if (check && lockmode != AccessExclusiveLock)
+ elog(ERROR, "AccessExclusiveLock required to add toast table.");
+
+ /*
+ * Create the toast table and its index
+ */
+ snprintf(toast_relname, sizeof(toast_relname),
+ "pg_toast_%u", relOid);
+ snprintf(toast_idxname, sizeof(toast_idxname),
+ "pg_toast_%u_index", relOid);
+
+ /* this is pretty painful... need a tuple descriptor */
+ tupdesc = CreateTemplateTupleDesc(3);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1,
+ "chunk_id",
+ OIDOID,
+ -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2,
+ "chunk_seq",
+ INT4OID,
+ -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3,
+ "chunk_data",
+ BYTEAOID,
+ -1, 0);
+
+ /*
+ * Ensure that the toast table doesn't itself get toasted, or we'll be
+ * toast :-(. This is essential for chunk_data because type bytea is
+ * toastable; hit the other two just to be sure.
+ */
+ TupleDescAttr(tupdesc, 0)->attstorage = TYPSTORAGE_PLAIN;
+ TupleDescAttr(tupdesc, 1)->attstorage = TYPSTORAGE_PLAIN;
+ TupleDescAttr(tupdesc, 2)->attstorage = TYPSTORAGE_PLAIN;
+
+ /*
+ * Toast tables for regular relations go in pg_toast; those for temp
+ * relations go into the per-backend temp-toast-table namespace.
+ */
+ if (isTempOrTempToastNamespace(rel->rd_rel->relnamespace))
+ namespaceid = GetTempToastNamespace();
+ else
+ namespaceid = PG_TOAST_NAMESPACE;
+
+ /*
+ * Use binary-upgrade override for pg_type.oid, if supplied. We might be
+ * in the post-schema-restore phase where we are doing ALTER TABLE to
+ * create TOAST tables that didn't exist in the old cluster.
+ */
+ if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_toast_pg_type_oid))
+ {
+ toast_typid = binary_upgrade_next_toast_pg_type_oid;
+ binary_upgrade_next_toast_pg_type_oid = InvalidOid;
+ }
+
+ /* Toast table is shared if and only if its parent is. */
+ shared_relation = rel->rd_rel->relisshared;
+
+ /* It's mapped if and only if its parent is, too */
+ mapped_relation = RelationIsMapped(rel);
+
+ toast_relid = heap_create_with_catalog(toast_relname,
+ namespaceid,
+ rel->rd_rel->reltablespace,
+ toastOid,
+ toast_typid,
+ InvalidOid,
+ rel->rd_rel->relowner,
+ table_relation_toast_am(rel),
+ tupdesc,
+ NIL,
+ RELKIND_TOASTVALUE,
+ rel->rd_rel->relpersistence,
+ shared_relation,
+ mapped_relation,
+ ONCOMMIT_NOOP,
+ reloptions,
+ false,
+ true,
+ true,
+ InvalidOid,
+ NULL);
+ Assert(toast_relid != InvalidOid);
+
+ /* make the toast relation visible, else table_open will fail */
+ CommandCounterIncrement();
+
+ /* ShareLock is not really needed here, but take it anyway */
+ toast_rel = table_open(toast_relid, ShareLock);
+
+ /*
+ * Create unique index on chunk_id, chunk_seq.
+ *
+ * NOTE: the normal TOAST access routines could actually function with a
+ * single-column index on chunk_id only. However, the slice access
+ * routines use both columns for faster access to an individual chunk. In
+ * addition, we want it to be unique as a check against the possibility of
+ * duplicate TOAST chunk OIDs. The index might also be a little more
+ * efficient this way, since btree isn't all that happy with large numbers
+ * of equal keys.
+ */
+
+ indexInfo = makeNode(IndexInfo);
+ indexInfo->ii_NumIndexAttrs = 2;
+ indexInfo->ii_NumIndexKeyAttrs = 2;
+ indexInfo->ii_IndexAttrNumbers[0] = 1;
+ indexInfo->ii_IndexAttrNumbers[1] = 2;
+ indexInfo->ii_Expressions = NIL;
+ indexInfo->ii_ExpressionsState = NIL;
+ indexInfo->ii_Predicate = NIL;
+ indexInfo->ii_PredicateState = NULL;
+ indexInfo->ii_ExclusionOps = NULL;
+ indexInfo->ii_ExclusionProcs = NULL;
+ indexInfo->ii_ExclusionStrats = NULL;
+ indexInfo->ii_OpclassOptions = NULL;
+ indexInfo->ii_Unique = true;
+ indexInfo->ii_ReadyForInserts = true;
+ indexInfo->ii_Concurrent = false;
+ indexInfo->ii_BrokenHotChain = false;
+ indexInfo->ii_ParallelWorkers = 0;
+ indexInfo->ii_Am = BTREE_AM_OID;
+ indexInfo->ii_AmCache = NULL;
+ indexInfo->ii_Context = CurrentMemoryContext;
+
+ collationObjectId[0] = InvalidOid;
+ collationObjectId[1] = InvalidOid;
+
+ classObjectId[0] = OID_BTREE_OPS_OID;
+ classObjectId[1] = INT4_BTREE_OPS_OID;
+
+ coloptions[0] = 0;
+ coloptions[1] = 0;
+
+ index_create(toast_rel, toast_idxname, toastIndexOid, InvalidOid,
+ InvalidOid, InvalidOid,
+ indexInfo,
+ list_make2("chunk_id", "chunk_seq"),
+ BTREE_AM_OID,
+ rel->rd_rel->reltablespace,
+ collationObjectId, classObjectId, coloptions, (Datum) 0,
+ INDEX_CREATE_IS_PRIMARY, 0, true, true, NULL);
+
+ table_close(toast_rel, NoLock);
+
+ /*
+ * Store the toast table's OID in the parent relation's pg_class row
+ */
+ class_rel = table_open(RelationRelationId, RowExclusiveLock);
+
+ reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
+ if (!HeapTupleIsValid(reltup))
+ elog(ERROR, "cache lookup failed for relation %u", relOid);
+
+ ((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid;
+
+ if (!IsBootstrapProcessingMode())
+ {
+ /* normal case, use a transactional update */
+ CatalogTupleUpdate(class_rel, &reltup->t_self, reltup);
+ }
+ else
+ {
+ /* While bootstrapping, we cannot UPDATE, so overwrite in-place */
+ heap_inplace_update(class_rel, reltup);
+ }
+
+ heap_freetuple(reltup);
+
+ table_close(class_rel, RowExclusiveLock);
+
+ /*
+ * Register dependency from the toast table to the master, so that the
+ * toast table will be deleted if the master is. Skip this in bootstrap
+ * mode.
+ */
+ if (!IsBootstrapProcessingMode())
+ {
+ baseobject.classId = RelationRelationId;
+ baseobject.objectId = relOid;
+ baseobject.objectSubId = 0;
+ toastobject.classId = RelationRelationId;
+ toastobject.objectId = toast_relid;
+ toastobject.objectSubId = 0;
+
+ recordDependencyOn(&toastobject, &baseobject, DEPENDENCY_INTERNAL);
+ }
+
+ /*
+ * Make changes visible
+ */
+ CommandCounterIncrement();
+
+ return true;
+}
+
+/*
+ * Check to see whether the table needs a TOAST table.
+ */
+static bool
+needs_toast_table(Relation rel)
+{
+ /*
+ * No need to create a TOAST table for partitioned tables.
+ */
+ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ return false;
+
+ /*
+ * We cannot allow toasting a shared relation after initdb (because
+ * there's no way to mark it toasted in other databases' pg_class).
+ */
+ if (rel->rd_rel->relisshared && !IsBootstrapProcessingMode())
+ return false;
+
+ /*
+ * Ignore attempts to create toast tables on catalog tables after initdb.
+ * Which catalogs get toast tables is explicitly chosen in
+ * catalog/toasting.h. (We could get here via some ALTER TABLE command if
+ * the catalog doesn't have a toast table.)
+ */
+ if (IsCatalogRelation(rel) && !IsBootstrapProcessingMode())
+ return false;
+
+ /* Otherwise, let the AM decide. */
+ return table_relation_needs_toast_table(rel);
+}