|
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