Thread: Proposal: manipulating pg_control file from Perl

Proposal: manipulating pg_control file from Perl

From
Aleksander Alekseev
Date:
Hi,

Previously it was pointed out [1] that manipulating the pg_control
file from Cluster.pm may be beneficial under certain conditions.

As an example, one can downgrade the catalog version in pg_control,
place input files for pg_upgrade, execute pg_upgrade and check the
results. This would allow writing TAP-tests for pg_upgrade easily, in
some cases at least. Perhaps there are other scenarios.

Unfortunately this can't be done at the moment. One of the reasons is
that the ControlFileData structure stores platform-dependent types
like `int`. The size of the structure and all the offsets within it
are variable. The second reason is that integer representation may be
little- or big-endian depending on the platform. The third reason is
that the alignment of the fields may differ even if we switch to types
of the known size like int32 / int64.

For named reasons, manipulating pg_upgrade from Perl is impractical,
considering the number of environments we support.

I see two possible solutions:

1) Provide a tool written in C that allows changing pg_control, e.g.
`pg_writecontoldata` or maybe a flat like `pg_controldata -w`. The
tool can be executed from Perl, so it shouldn't know about
sizeof(int), alignment and endiness.

2) Change the format of pg_control to platform-independent,
semi-textual perhaps. The reason why it should be semi- is that we
should store the checksum of the file and I think it should have a
fixed offset. For instance:

```
# This is auto-generated file, don't edit!
checksum=AABBCCDD
pg_conrol_version=1800
cat_version=202503131
... etc ...
```

In case (2) we may consider getting rid of the pg_controldata tool.

Thoughts?

[1]: https://www.postgresql.org/message-id/ZzVOTc3ZgPWfEQut%40paquier.xyz

-- 
Best regards,
Aleksander Alekseev



Re: Proposal: manipulating pg_control file from Perl

From
Tom Lane
Date:
Aleksander Alekseev <aleksander@timescale.com> writes:
> Previously it was pointed out [1] that manipulating the pg_control
> file from Cluster.pm may be beneficial under certain conditions.

> As an example, one can downgrade the catalog version in pg_control,
> place input files for pg_upgrade, execute pg_upgrade and check the
> results. This would allow writing TAP-tests for pg_upgrade easily, in
> some cases at least. Perhaps there are other scenarios.

I'm finding it *really* hard to buy that as a credible use-case.
There is no situation where changing the catalog version in
pg_control, by itself, is a useful thing to do: you'd have to also
install matching catalog contents.  But then wherever you got the
catalog contents from would be a perfectly good source for a matching
pg_control, no?  Likewise, the idea that pg_control should be
architecture-independent when none of the catalogs or data files are
seems pretty pointless.

Maybe there's a case to be made for doing something here, but you
haven't made it.

            regards, tom lane



Re: Proposal: manipulating pg_control file from Perl

From
Dagfinn Ilmari Mannsåker
Date:
Aleksander Alekseev <aleksander@timescale.com> writes:

> Hi,
>
> Previously it was pointed out [1] that manipulating the pg_control
> file from Cluster.pm may be beneficial under certain conditions.
[...]
> Unfortunately this can't be done at the moment. One of the reasons is
> that the ControlFileData structure stores platform-dependent types
> like `int`. The size of the structure and all the offsets within it
> are variable. The second reason is that integer representation may be
> little- or big-endian depending on the platform. The third reason is
> that the alignment of the fields may differ even if we switch to types
> of the known size like int32 / int64.

Notwitstanding Tom's objections, these are not reasons for not being
able to manipulate these values from Perl.  The `i` and `I` formats for
pack/unpack (see https://perldoc.perl.org/functions/pack) use what the C
compiler calls `int`, in terms of both endianness and size.

> For named reasons, manipulating pg_upgrade from Perl is impractical,
> considering the number of environments we support.
>
> I see two possible solutions:
>
> 1) Provide a tool written in C that allows changing pg_control, e.g.
> `pg_writecontoldata` or maybe a flat like `pg_controldata -w`. The
> tool can be executed from Perl, so it shouldn't know about
> sizeof(int), alignment and endiness.

1.5) Use Perl's pack/unpack functions, which are explicitly desgined for
     exactly this use case.

- ilmari



Re: Proposal: manipulating pg_control file from Perl

From
Aleksander Alekseev
Date:
Hi Dagfinn,

> Notwitstanding Tom's objections, these are not reasons for not being
> able to manipulate these values from Perl.  The `i` and `I` formats for
> pack/unpack (see https://perldoc.perl.org/functions/pack) use what the C
> compiler calls `int`, in terms of both endianness and size.
>
> > For named reasons, manipulating pg_upgrade from Perl is impractical,
> > considering the number of environments we support.
> >
> > I see two possible solutions:
> >
> > 1) Provide a tool written in C that allows changing pg_control, e.g.
> > `pg_writecontoldata` or maybe a flat like `pg_controldata -w`. The
> > tool can be executed from Perl, so it shouldn't know about
> > sizeof(int), alignment and endiness.
>
> 1.5) Use Perl's pack/unpack functions, which are explicitly desgined for
>      exactly this use case.

Thanks for your reply.

It is my understanding that Perl is not extremely aware of alignment.
For instance if I want to modify the checksum of the file and the
offset of the checksum is let's say 200 bytes on one platform, 204 on
another and 208 on a third, pack/unpack will not help me.

Or did I miss something?

-- 
Best regards,
Aleksander Alekseev



Re: Proposal: manipulating pg_control file from Perl

From
Christoph Berg
Date:
Re: Aleksander Alekseev
> 1) Provide a tool written in C that allows changing pg_control, e.g.
> `pg_writecontoldata` or maybe a flat like `pg_controldata -w`.

I thought we already had pg_resetwal for that.

Christoph



Re: Proposal: manipulating pg_control file from Perl

From
Aleksander Alekseev
Date:
Hi Christoph,

> Re: Aleksander Alekseev
> > 1) Provide a tool written in C that allows changing pg_control, e.g.
> > `pg_writecontoldata` or maybe a flat like `pg_controldata -w`.
>
> I thought we already had pg_resetwal for that.

That's a good point.

In the case I referred to [1] however I wanted to manipulate more
fields than pg_resetwal currently allows, e.g. catalog version -
which, as Tom pointed out, is a controversial thing to do in a TAP
test.

Do you think pg_resetwall should be able to do more than it currently
does, or merely pointing out that we already have a tool for editing
pg_control file?

73s de Alex, R2AUK

[1]: https://postgr.es/m/CAJ7c6TOy7fUW9MuNeOWor3cSFnQg9tgz%3DmjXHDb94GORtM_Eyg%40mail.gmail.com



Re: Proposal: manipulating pg_control file from Perl

From
Christoph Berg
Date:
Re: Aleksander Alekseev
> Do you think pg_resetwall should be able to do more than it currently
> does, or merely pointing out that we already have a tool for editing
> pg_control file?

I don't know if being able to mess with these fields makes sense, but
if so, pg_resetwal seems like the correct place to put it.

> 73s de Alex, R2AUK

73 TU :)

Christoph



Re: Proposal: manipulating pg_control file from Perl

From
Dagfinn Ilmari Mannsåker
Date:
Aleksander Alekseev <aleksander@timescale.com> writes:

> Hi Dagfinn,
>
>> Notwitstanding Tom's objections, these are not reasons for not being
>> able to manipulate these values from Perl.  The `i` and `I` formats for
>> pack/unpack (see https://perldoc.perl.org/functions/pack) use what the C
>> compiler calls `int`, in terms of both endianness and size.
>>
>> > For named reasons, manipulating pg_upgrade from Perl is impractical,
>> > considering the number of environments we support.
>> >
>> > I see two possible solutions:
>> >
>> > 1) Provide a tool written in C that allows changing pg_control, e.g.
>> > `pg_writecontoldata` or maybe a flat like `pg_controldata -w`. The
>> > tool can be executed from Perl, so it shouldn't know about
>> > sizeof(int), alignment and endiness.
>>
>> 1.5) Use Perl's pack/unpack functions, which are explicitly desgined for
>>      exactly this use case.
>
> Thanks for your reply.
>
> It is my understanding that Perl is not extremely aware of alignment.
> For instance if I want to modify the checksum of the file and the
> offset of the checksum is let's say 200 bytes on one platform, 204 on
> another and 208 on a third, pack/unpack will not help me.
>
> Or did I miss something?

You have to specify alignment manually using the `x![$type]` notation.
I actually wrote up a pack template for the entire control file
(assuming all types have alignof==sizeof), and it seems to work.  Run
the attached with a Postgres 17 data directory as the arguemnt, and it
should show all the fields.

- ilmari


Attachment

Re: Proposal: manipulating pg_control file from Perl

From
Aleksander Alekseev
Date:
Hi,

> > It is my understanding that Perl is not extremely aware of alignment.
> > For instance if I want to modify the checksum of the file and the
> > offset of the checksum is let's say 200 bytes on one platform, 204 on
> > another and 208 on a third, pack/unpack will not help me.
> >
> > Or did I miss something?
>
> You have to specify alignment manually using the `x![$type]` notation.
> I actually wrote up a pack template for the entire control file
> (assuming all types have alignof==sizeof), and it seems to work.  Run
> the attached with a Postgres 17 data directory as the arguemnt, and it
> should show all the fields.

Oh that's neat. Thanks for sharing!

-- 
Best regards,
Aleksander Alekseev