1 #----------------------------------------------------------------------
4 # Perl module that extracts info from catalog headers into Perl
7 # Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
8 # Portions Copyright (c) 1994, Regents of the University of California
10 # src/backend/catalog/Catalog.pm
12 #----------------------------------------------------------------------
20 our @ISA = qw(Exporter);
22 our @EXPORT_OK = qw(Catalogs RenameTempFile);
24 # Call this function with an array of names of header files to parse.
25 # Returns a nested data structure describing the data in the headers.
28 my (%catalogs, $catname, $declaring_attributes, $most_recent);
29 $catalogs{names} = [];
31 # There are a few types which are given one name in the C source, but a
32 # different name at the SQL level. These are enumerated here.
33 my %RENAME_ATTTYPE = (
38 'TransactionId' => 'xid');
40 foreach my $input_file (@_)
43 $catalog{columns} = [];
46 open(INPUT_FILE, '<', $input_file) || die "$input_file: $!";
48 # Scan the input file.
52 # Strip C-style comments.
57 # handle multi-line comments properly.
58 my $next_line = <INPUT_FILE>;
59 die "$input_file: ends within C-style comment\n"
60 if !defined $next_line;
65 # Strip useless whitespace and trailing semicolons.
71 # Push the data into the appropriate data structure.
72 if (/^DATA\(insert(\s+OID\s+=\s+(\d+))?\s+\(\s*(.*)\s*\)\s*\)$/)
74 push @{ $catalog{data} }, { oid => $2, bki_values => $3 };
76 elsif (/^DESCR\(\"(.*)\"\)$/)
78 $most_recent = $catalog{data}->[-1];
80 # this tests if most recent line is not a DATA() statement
81 if (ref $most_recent ne 'HASH')
83 die "DESCR() does not apply to any catalog ($input_file)";
85 if (!defined $most_recent->{oid})
87 die "DESCR() does not apply to any oid ($input_file)";
91 $most_recent->{descr} = $1;
94 elsif (/^SHDESCR\(\"(.*)\"\)$/)
96 $most_recent = $catalog{data}->[-1];
98 # this tests if most recent line is not a DATA() statement
99 if (ref $most_recent ne 'HASH')
102 "SHDESCR() does not apply to any catalog ($input_file)";
104 if (!defined $most_recent->{oid})
106 die "SHDESCR() does not apply to any oid ($input_file)";
110 $most_recent->{shdescr} = $1;
113 elsif (/^DECLARE_TOAST\(\s*(\w+),\s*(\d+),\s*(\d+)\)/)
115 $catname = 'toasting';
116 my ($toast_name, $toast_oid, $index_oid) = ($1, $2, $3);
117 push @{ $catalog{data} },
118 "declare toast $toast_oid $index_oid on $toast_name\n";
120 elsif (/^DECLARE_(UNIQUE_)?INDEX\(\s*(\w+),\s*(\d+),\s*(.+)\)/)
122 $catname = 'indexing';
123 my ($is_unique, $index_name, $index_oid, $using) =
125 push @{ $catalog{data} },
127 "declare %sindex %s %s %s\n",
128 $is_unique ? 'unique ' : '',
129 $index_name, $index_oid, $using);
131 elsif (/^BUILD_INDICES/)
133 push @{ $catalog{data} }, "build indices\n";
135 elsif (/^CATALOG\(([^,]*),(\d+)\)/)
138 $catalog{relation_oid} = $2;
140 # Store pg_* catalog names in the same order we receive them
141 push @{ $catalogs{names} }, $catname;
143 $catalog{bootstrap} = /BKI_BOOTSTRAP/ ? ' bootstrap' : '';
144 $catalog{shared_relation} =
145 /BKI_SHARED_RELATION/ ? ' shared_relation' : '';
146 $catalog{without_oids} =
147 /BKI_WITHOUT_OIDS/ ? ' without_oids' : '';
148 $catalog{rowtype_oid} =
149 /BKI_ROWTYPE_OID\((\d+)\)/ ? " rowtype_oid $1" : '';
150 $catalog{schema_macro} = /BKI_SCHEMA_MACRO/ ? 'True' : '';
151 $declaring_attributes = 1;
153 elsif ($declaring_attributes)
159 undef $declaring_attributes;
163 my ($atttype, $attname) = split /\s+/, $_;
164 die "parse error ($input_file)" unless $attname;
165 if (exists $RENAME_ATTTYPE{$atttype})
167 $atttype = $RENAME_ATTTYPE{$atttype};
169 if ($attname =~ /(.*)\[.*\]/) # array attribute
172 $atttype .= '[]'; # variable-length only
174 push @{ $catalog{columns} }, { $attname => $atttype };
178 $catalogs{$catname} = \%catalog;
184 # Rename temporary files to final names.
185 # Call this function with the final file name and the .tmp extension
186 # Note: recommended extension is ".tmp$$", so that parallel make steps
187 # can't use the same temp files
190 my $final_name = shift;
191 my $extension = shift;
192 my $temp_name = $final_name . $extension;
193 print "Writing $final_name\n";
194 rename($temp_name, $final_name) || die "rename: $temp_name: $!";