|
156 | 156 | print $bki "open $catname\n";
|
157 | 157 | }
|
158 | 158 |
|
159 |
| - if (defined $catalog->{data}) |
| 159 | + # For pg_attribute.h, we generate data entries ourselves. |
| 160 | + # NB: pg_type.h must come before pg_attribute.h in the input list |
| 161 | + # of catalog names, since we use info from pg_type.h here. |
| 162 | + if ($catname eq 'pg_attribute') |
160 | 163 | {
|
| 164 | + gen_pg_attribute($schema, @attnames); |
| 165 | + } |
161 | 166 |
|
162 |
| - # Ordinary catalog with DATA line(s) |
163 |
| - foreach my $row (@{ $catalog->{data} }) |
164 |
| - { |
165 |
| - |
166 |
| - # Split line into tokens without interpreting their meaning. |
167 |
| - my %bki_values; |
168 |
| - @bki_values{@attnames} = |
169 |
| - Catalog::SplitDataLine($row->{bki_values}); |
170 |
| - |
171 |
| - # Perform required substitutions on fields |
172 |
| - foreach my $column (@$schema) |
173 |
| - { |
174 |
| - my $attname = $column->{name}; |
175 |
| - my $atttype = $column->{type}; |
176 |
| - |
177 |
| - # Substitute constant values we acquired above. |
178 |
| - # (It's intentional that this can apply to parts of a field). |
179 |
| - $bki_values{$attname} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g; |
180 |
| - $bki_values{$attname} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g; |
181 |
| - |
182 |
| - # Replace regproc columns' values with OIDs. |
183 |
| - # If we don't have a unique value to substitute, |
184 |
| - # just do nothing (regprocin will complain). |
185 |
| - if ($atttype eq 'regproc') |
186 |
| - { |
187 |
| - my $procoid = $regprocoids{ $bki_values{$attname} }; |
188 |
| - $bki_values{$attname} = $procoid |
189 |
| - if defined($procoid) && $procoid ne 'MULTIPLE'; |
190 |
| - } |
191 |
| - } |
| 167 | + # Ordinary catalog with DATA line(s) |
| 168 | + foreach my $row (@{ $catalog->{data} }) |
| 169 | + { |
192 | 170 |
|
193 |
| - # Save pg_proc oids for use in later regproc substitutions. |
194 |
| - # This relies on the order we process the files in! |
195 |
| - if ($catname eq 'pg_proc') |
196 |
| - { |
197 |
| - if (defined($regprocoids{ $bki_values{proname} })) |
198 |
| - { |
199 |
| - $regprocoids{ $bki_values{proname} } = 'MULTIPLE'; |
200 |
| - } |
201 |
| - else |
202 |
| - { |
203 |
| - $regprocoids{ $bki_values{proname} } = $row->{oid}; |
204 |
| - } |
205 |
| - } |
| 171 | + # Split line into tokens without interpreting their meaning. |
| 172 | + my %bki_values; |
| 173 | + @bki_values{@attnames} = |
| 174 | + Catalog::SplitDataLine($row->{bki_values}); |
206 | 175 |
|
207 |
| - # Save pg_type info for pg_attribute processing below |
208 |
| - if ($catname eq 'pg_type') |
| 176 | + # Perform required substitutions on fields |
| 177 | + foreach my $column (@$schema) |
| 178 | + { |
| 179 | + my $attname = $column->{name}; |
| 180 | + my $atttype = $column->{type}; |
| 181 | + |
| 182 | + # Substitute constant values we acquired above. |
| 183 | + # (It's intentional that this can apply to parts of a field). |
| 184 | + $bki_values{$attname} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g; |
| 185 | + $bki_values{$attname} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g; |
| 186 | + |
| 187 | + # Replace regproc columns' values with OIDs. |
| 188 | + # If we don't have a unique value to substitute, |
| 189 | + # just do nothing (regprocin will complain). |
| 190 | + if ($atttype eq 'regproc') |
209 | 191 | {
|
210 |
| - my %type = %bki_values; |
211 |
| - $type{oid} = $row->{oid}; |
212 |
| - $types{ $type{typname} } = \%type; |
| 192 | + my $procoid = $regprocoids{ $bki_values{$attname} }; |
| 193 | + $bki_values{$attname} = $procoid |
| 194 | + if defined($procoid) && $procoid ne 'MULTIPLE'; |
213 | 195 | }
|
| 196 | + } |
214 | 197 |
|
215 |
| - # Write to postgres.bki |
216 |
| - my $oid = $row->{oid} ? "OID = $row->{oid} " : ''; |
217 |
| - printf $bki "insert %s( %s )\n", $oid, |
218 |
| - join(' ', @bki_values{@attnames}); |
219 |
| - |
220 |
| - # Write comments to postgres.description and |
221 |
| - # postgres.shdescription |
222 |
| - if (defined $row->{descr}) |
| 198 | + # Save pg_proc oids for use in later regproc substitutions. |
| 199 | + # This relies on the order we process the files in! |
| 200 | + if ($catname eq 'pg_proc') |
| 201 | + { |
| 202 | + if (defined($regprocoids{ $bki_values{proname} })) |
223 | 203 | {
|
224 |
| - printf $descr "%s\t%s\t0\t%s\n", |
225 |
| - $row->{oid}, $catname, $row->{descr}; |
| 204 | + $regprocoids{ $bki_values{proname} } = 'MULTIPLE'; |
226 | 205 | }
|
227 |
| - if (defined $row->{shdescr}) |
| 206 | + else |
228 | 207 | {
|
229 |
| - printf $shdescr "%s\t%s\t%s\n", |
230 |
| - $row->{oid}, $catname, $row->{shdescr}; |
| 208 | + $regprocoids{ $bki_values{proname} } = $row->{oid}; |
231 | 209 | }
|
232 | 210 | }
|
233 |
| - } |
234 |
| - if ($catname eq 'pg_attribute') |
235 |
| - { |
236 | 211 |
|
237 |
| - # For pg_attribute.h, we generate DATA entries ourselves. |
238 |
| - # NB: pg_type.h must come before pg_attribute.h in the input list |
239 |
| - # of catalog names, since we use info from pg_type.h here. |
240 |
| - foreach my $table_name (@{ $catalogs->{names} }) |
| 212 | + # Save pg_type info for pg_attribute processing below |
| 213 | + if ($catname eq 'pg_type') |
241 | 214 | {
|
242 |
| - my $table = $catalogs->{$table_name}; |
243 |
| - |
244 |
| - # Currently, all bootstrapped relations also need schemapg.h |
245 |
| - # entries, so skip if the relation isn't to be in schemapg.h. |
246 |
| - next if !$table->{schema_macro}; |
247 |
| - |
248 |
| - $schemapg_entries{$table_name} = []; |
249 |
| - push @tables_needing_macros, $table_name; |
250 |
| - |
251 |
| - # Generate entries for user attributes. |
252 |
| - my $attnum = 0; |
253 |
| - my $priornotnull = 1; |
254 |
| - foreach my $attr (@{ $table->{columns} }) |
255 |
| - { |
256 |
| - $attnum++; |
257 |
| - my %row; |
258 |
| - $row{attnum} = $attnum; |
259 |
| - $row{attrelid} = $table->{relation_oid}; |
260 |
| - |
261 |
| - morph_row_for_pgattr(\%row, $schema, $attr, $priornotnull); |
262 |
| - $priornotnull &= ($row{attnotnull} eq 't'); |
263 |
| - |
264 |
| - # If it's bootstrapped, put an entry in postgres.bki. |
265 |
| - print_bki_insert(\%row, @attnames) if $table->{bootstrap}; |
| 215 | + my %type = %bki_values; |
| 216 | + $type{oid} = $row->{oid}; |
| 217 | + $types{ $type{typname} } = \%type; |
| 218 | + } |
266 | 219 |
|
267 |
| - # Store schemapg entries for later. |
268 |
| - morph_row_for_schemapg(\%row, $schema); |
269 |
| - push @{ $schemapg_entries{$table_name} }, |
270 |
| - sprintf "{ %s }", |
271 |
| - join(', ', grep { defined $_ } @row{@attnames}); |
272 |
| - } |
| 220 | + # Write to postgres.bki |
| 221 | + my $oid = $row->{oid} ? "OID = $row->{oid} " : ''; |
| 222 | + printf $bki "insert %s( %s )\n", $oid, |
| 223 | + join(' ', @bki_values{@attnames}); |
273 | 224 |
|
274 |
| - # Generate entries for system attributes. |
275 |
| - # We only need postgres.bki entries, not schemapg.h entries. |
276 |
| - if ($table->{bootstrap}) |
277 |
| - { |
278 |
| - $attnum = 0; |
279 |
| - my @SYS_ATTRS = ( |
280 |
| - { name => 'ctid', type => 'tid' }, |
281 |
| - { name => 'oid', type => 'oid' }, |
282 |
| - { name => 'xmin', type => 'xid' }, |
283 |
| - { name => 'cmin', type => 'cid' }, |
284 |
| - { name => 'xmax', type => 'xid' }, |
285 |
| - { name => 'cmax', type => 'cid' }, |
286 |
| - { name => 'tableoid', type => 'oid' }); |
287 |
| - foreach my $attr (@SYS_ATTRS) |
288 |
| - { |
289 |
| - $attnum--; |
290 |
| - my %row; |
291 |
| - $row{attnum} = $attnum; |
292 |
| - $row{attrelid} = $table->{relation_oid}; |
293 |
| - $row{attstattarget} = '0'; |
294 |
| - |
295 |
| - # Omit the oid column if the catalog doesn't have them |
296 |
| - next |
297 |
| - if $table->{without_oids} |
298 |
| - && $attr->{name} eq 'oid'; |
299 |
| - |
300 |
| - morph_row_for_pgattr(\%row, $schema, $attr, 1); |
301 |
| - print_bki_insert(\%row, @attnames); |
302 |
| - } |
303 |
| - } |
| 225 | + # Write comments to postgres.description and |
| 226 | + # postgres.shdescription |
| 227 | + if (defined $row->{descr}) |
| 228 | + { |
| 229 | + printf $descr "%s\t%s\t0\t%s\n", |
| 230 | + $row->{oid}, $catname, $row->{descr}; |
| 231 | + } |
| 232 | + if (defined $row->{shdescr}) |
| 233 | + { |
| 234 | + printf $shdescr "%s\t%s\t%s\n", |
| 235 | + $row->{oid}, $catname, $row->{shdescr}; |
304 | 236 | }
|
305 | 237 | }
|
306 | 238 |
|
|
375 | 307 | #################### Subroutines ########################
|
376 | 308 |
|
377 | 309 |
|
| 310 | +# For each catalog marked as needing a schema macro, generate the |
| 311 | +# per-user-attribute data to be incorporated into schemapg.h. Also, for |
| 312 | +# bootstrap catalogs, emit pg_attribute entries into the .bki file |
| 313 | +# for both user and system attributes. |
| 314 | +sub gen_pg_attribute |
| 315 | +{ |
| 316 | + my $schema = shift; |
| 317 | + my @attnames = @_; |
| 318 | + |
| 319 | + foreach my $table_name (@{ $catalogs->{names} }) |
| 320 | + { |
| 321 | + my $table = $catalogs->{$table_name}; |
| 322 | + |
| 323 | + # Currently, all bootstrapped relations also need schemapg.h |
| 324 | + # entries, so skip if the relation isn't to be in schemapg.h. |
| 325 | + next if !$table->{schema_macro}; |
| 326 | + |
| 327 | + $schemapg_entries{$table_name} = []; |
| 328 | + push @tables_needing_macros, $table_name; |
| 329 | + |
| 330 | + # Generate entries for user attributes. |
| 331 | + my $attnum = 0; |
| 332 | + my $priornotnull = 1; |
| 333 | + foreach my $attr (@{ $table->{columns} }) |
| 334 | + { |
| 335 | + $attnum++; |
| 336 | + my %row; |
| 337 | + $row{attnum} = $attnum; |
| 338 | + $row{attrelid} = $table->{relation_oid}; |
| 339 | + |
| 340 | + morph_row_for_pgattr(\%row, $schema, $attr, $priornotnull); |
| 341 | + $priornotnull &= ($row{attnotnull} eq 't'); |
| 342 | + |
| 343 | + # If it's bootstrapped, put an entry in postgres.bki. |
| 344 | + print_bki_insert(\%row, @attnames) if $table->{bootstrap}; |
| 345 | + |
| 346 | + # Store schemapg entries for later. |
| 347 | + morph_row_for_schemapg(\%row, $schema); |
| 348 | + push @{ $schemapg_entries{$table_name} }, |
| 349 | + sprintf "{ %s }", |
| 350 | + join(', ', grep { defined $_ } @row{@attnames}); |
| 351 | + } |
| 352 | + |
| 353 | + # Generate entries for system attributes. |
| 354 | + # We only need postgres.bki entries, not schemapg.h entries. |
| 355 | + if ($table->{bootstrap}) |
| 356 | + { |
| 357 | + $attnum = 0; |
| 358 | + my @SYS_ATTRS = ( |
| 359 | + { name => 'ctid', type => 'tid' }, |
| 360 | + { name => 'oid', type => 'oid' }, |
| 361 | + { name => 'xmin', type => 'xid' }, |
| 362 | + { name => 'cmin', type => 'cid' }, |
| 363 | + { name => 'xmax', type => 'xid' }, |
| 364 | + { name => 'cmax', type => 'cid' }, |
| 365 | + { name => 'tableoid', type => 'oid' }); |
| 366 | + foreach my $attr (@SYS_ATTRS) |
| 367 | + { |
| 368 | + $attnum--; |
| 369 | + my %row; |
| 370 | + $row{attnum} = $attnum; |
| 371 | + $row{attrelid} = $table->{relation_oid}; |
| 372 | + $row{attstattarget} = '0'; |
| 373 | + |
| 374 | + # Omit the oid column if the catalog doesn't have them |
| 375 | + next |
| 376 | + if $table->{without_oids} |
| 377 | + && $attr->{name} eq 'oid'; |
| 378 | + |
| 379 | + morph_row_for_pgattr(\%row, $schema, $attr, 1); |
| 380 | + print_bki_insert(\%row, @attnames); |
| 381 | + } |
| 382 | + } |
| 383 | + } |
| 384 | +} |
| 385 | + |
378 | 386 | # Given $pgattr_schema (the pg_attribute schema for a catalog sufficient for
|
379 | 387 | # AddDefaultValues), $attr (the description of a catalog row), and
|
380 | 388 | # $priornotnull (whether all prior attributes in this catalog are not null),
|
|
0 commit comments