Thread

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Doc: Add documentation for sequence synchronization.

  2. Remove unused assignment in CREATE PUBLICATION grammar.

  3. Add seq_sync_error_count to subscription statistics.

  4. Fix few issues in commit 5509055d69.

  5. Add sequence synchronization for logical replication.

  6. Add worker type argument to logical replication worker functions.

  7. Introduce "REFRESH SEQUENCES" for subscriptions.

  8. Refactor logical worker synchronization code into a separate file.

  9. Standardize use of REFRESH PUBLICATION in code and messages.

  10. Add "ALL SEQUENCES" support to publications.

  11. Expose sequence page LSN via pg_get_sequence_data.

  12. Resume conflict-relevant data retention automatically.

  13. Post-commit review fixes for 228c370868.

  14. Generate GUC tables from .dat file

  1. Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-04T10:57:03Z

    In the past, we have discussed various approaches to replicate
    sequences by decoding the sequence changes from WAL. However, we faced
    several challenges to achieve the same, some of which are due to the
    non-transactional nature of sequences. The major ones were: (a)
    correctness of the decoding part, some of the problems were discussed
    at [1][2][3] (b) handling of sequences especially adding certain
    sequences automatically (e.g. sequences backing SERIAL/BIGSERIAL
    columns) for built-in logical replication is not considered in the
    proposed work [1] (c) there were some performance concerns in not so
    frequent scenarios [4] (see performance issues), we can probably deal
    with this by making sequences optional for builtin logical replication
    
    It could be possible that we can deal with these and any other issues
    with more work but as the use case for this feature is primarily major
    version upgrades it is not clear that we want to make such a big
    change to the code or are there better alternatives to achieve the
    same.
    
    This time at pgconf.dev (https://2024.pgconf.dev/), we discussed
    alternative approaches for this work which I would like to summarize.
    The various methods we discussed are as follows:
    
    1. Provide a tool to copy all the sequences from publisher to
    subscriber. The major drawback is that users need to perform this as
    an additional step during the upgrade which would be inconvenient and
    probably not as useful as some built-in mechanism.
    2. Provide a command say Alter Subscription ...  Replicate Sequences
    (or something like that) which users can perform before shutdown of
    the publisher node during upgrade. This will allow copying all the
    sequences from the publisher node to the subscriber node directly.
    Similar to previous approach, this could also be inconvenient for
    users.
    3. Replicate published sequences via walsender at the time of shutdown
    or incrementally while decoding checkpoint record. The two ways to
    achieve this are: (a) WAL log a special NOOP record just before
    shutting down checkpointer. Then allow the WALsender to read the
    sequence data and send it to the subscriber while decoding the new
    NOOP record. (b) Similar to the previous idea but instead of WAL
    logging a new record directly invokes a decoding callback after
    walsender receives a request to shutdown which will allow pgoutput to
    read and send required sequences. This approach has a drawback that we
    are adding more work at the time of shutdown but note that we already
    waits for all the WAL records to be decoded and sent before shutting
    down the walsender during shutdown of the node.
    
    Any other ideas?
    
    I have added the members I remember that were part of the discussion
    in the email. Please feel free to correct me if I have misunderstood
    or missed any point we talked about.
    
    Thoughts?
    
    [1] - https://www.postgresql.org/message-id/e4145f77-6f37-40e0-a770-aba359c50b93%40enterprisedb.com
    [2] - https://www.postgresql.org/message-id/CAA4eK1Lxt%2B5a9fA-B7FRzfd1vns%3DEwZTF5z9_xO9Ms4wsqD88Q%40mail.gmail.com
    [3] - https://www.postgresql.org/message-id/CAA4eK1KR4%3DyALKP0pOdVkqUwoUqD_v7oU3HzY-w0R_EBvgHL2w%40mail.gmail.com
    [4] - https://www.postgresql.org/message-id/12822961-b7de-9d59-dd27-2e3dc3980c7e%40enterprisedb.com
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  2. Re: Logical Replication of sequences

    Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com> — 2024-06-04T11:22:55Z

    Hi,
    
    On Tue, Jun 4, 2024 at 4:27 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > 3. Replicate published sequences via walsender at the time of shutdown
    > or incrementally while decoding checkpoint record. The two ways to
    > achieve this are: (a) WAL log a special NOOP record just before
    > shutting down checkpointer. Then allow the WALsender to read the
    > sequence data and send it to the subscriber while decoding the new
    > NOOP record. (b) Similar to the previous idea but instead of WAL
    > logging a new record directly invokes a decoding callback after
    > walsender receives a request to shutdown which will allow pgoutput to
    > read and send required sequences. This approach has a drawback that we
    > are adding more work at the time of shutdown but note that we already
    > waits for all the WAL records to be decoded and sent before shutting
    > down the walsender during shutdown of the node.
    
    Thanks. IIUC, both of the above approaches decode the sequences during
    only shutdown. I'm wondering, why not periodically decode and
    replicate the published sequences so that the decoding at the shutdown
    will not take that longer? I can imagine a case where there are tens
    of thousands of sequences in a production server, and surely decoding
    and sending them just during the shutdown can take a lot of time
    hampering the overall server uptime.
    
    --
    Bharath Rupireddy
    PostgreSQL Contributors Team
    RDS Open Source Databases
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  3. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-04T12:10:08Z

    On Tue, Jun 4, 2024 at 4:53 PM Bharath Rupireddy
    <bharath.rupireddyforpostgres@gmail.com> wrote:
    >
    > On Tue, Jun 4, 2024 at 4:27 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > 3. Replicate published sequences via walsender at the time of shutdown
    > > or incrementally while decoding checkpoint record. The two ways to
    > > achieve this are: (a) WAL log a special NOOP record just before
    > > shutting down checkpointer. Then allow the WALsender to read the
    > > sequence data and send it to the subscriber while decoding the new
    > > NOOP record. (b) Similar to the previous idea but instead of WAL
    > > logging a new record directly invokes a decoding callback after
    > > walsender receives a request to shutdown which will allow pgoutput to
    > > read and send required sequences. This approach has a drawback that we
    > > are adding more work at the time of shutdown but note that we already
    > > waits for all the WAL records to be decoded and sent before shutting
    > > down the walsender during shutdown of the node.
    >
    > Thanks. IIUC, both of the above approaches decode the sequences during
    > only shutdown. I'm wondering, why not periodically decode and
    > replicate the published sequences so that the decoding at the shutdown
    > will not take that longer?
    >
    
    Even if we decode it periodically (say each time we decode the
    checkpoint record) then also we need to send the entire set of
    sequences at shutdown. This is because the sequences may have changed
    from the last time we sent them.
    
    >
    > I can imagine a case where there are tens
    > of thousands of sequences in a production server, and surely decoding
    > and sending them just during the shutdown can take a lot of time
    > hampering the overall server uptime.
    >
    
    It is possible but we will send only the sequences that belong to
    publications for which walsender is supposed to send the required
    data. Now, we can also imagine providing option 2 (Alter Subscription
    ... Replicate Sequences) so that users can replicate sequences before
    shutdown and then disable the subscriptions so that there won't be a
    corresponding walsender.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  4. Re: Logical Replication of sequences

    Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> — 2024-06-04T14:09:46Z

    On Tue, Jun 4, 2024 at 4:27 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    
    >
    > 3. Replicate published sequences via walsender at the time of shutdown
    > or incrementally while decoding checkpoint record. The two ways to
    > achieve this are: (a) WAL log a special NOOP record just before
    > shutting down checkpointer. Then allow the WALsender to read the
    > sequence data and send it to the subscriber while decoding the new
    > NOOP record. (b) Similar to the previous idea but instead of WAL
    > logging a new record directly invokes a decoding callback after
    > walsender receives a request to shutdown which will allow pgoutput to
    > read and send required sequences. This approach has a drawback that we
    > are adding more work at the time of shutdown but note that we already
    > waits for all the WAL records to be decoded and sent before shutting
    > down the walsender during shutdown of the node.
    >
    > Any other ideas?
    >
    >
    In case of primary crash the sequence won't get replicated. That is true
    even with the previous approach in case walsender is shut down because of a
    crash, but it is more serious with this approach. How about periodically
    sending this information?
    
    -- 
    Best Wishes,
    Ashutosh Bapat
    
  5. Re: Logical Replication of sequences

    Yogesh Sharma <yogesh.sharma@catprosystems.com> — 2024-06-04T15:26:47Z

    On 6/4/24 06:57, Amit Kapila wrote:
    > 1. Provide a tool to copy all the sequences from publisher to
    > subscriber. The major drawback is that users need to perform this as
    > an additional step during the upgrade which would be inconvenient and
    > probably not as useful as some built-in mechanism.
    
    Agree, this requires additional steps. Not a preferred approach in my
    opinion. When a large set of sequences are present, it will add
    additional downtime for upgrade process.
    
    > 2. Provide a command say Alter Subscription ...  Replicate Sequences
    > (or something like that) which users can perform before shutdown of
    > the publisher node during upgrade. This will allow copying all the
    > sequences from the publisher node to the subscriber node directly.
    > Similar to previous approach, this could also be inconvenient for
    > users.
    
    This is similar to option 1 except that it is a SQL command now. Still
    not a preferred approach in my opinion. When a large set of sequences are
    present, it will add additional downtime for upgrade process.
    
    
    > 3. Replicate published sequences via walsender at the time of shutdown
    > or incrementally while decoding checkpoint record. The two ways to
    > achieve this are: (a) WAL log a special NOOP record just before
    > shutting down checkpointer. Then allow the WALsender to read the
    > sequence data and send it to the subscriber while decoding the new
    > NOOP record. (b) Similar to the previous idea but instead of WAL
    > logging a new record directly invokes a decoding callback after
    > walsender receives a request to shutdown which will allow pgoutput to
    > read and send required sequences. This approach has a drawback that we
    > are adding more work at the time of shutdown but note that we already
    > waits for all the WAL records to be decoded and sent before shutting
    > down the walsender during shutdown of the node.
    
    At the time of shutdown a) most logical upgrades don't necessarily call
    for shutdown b) it will still add to total downtime with large set of
    sequences. Incremental option is better as it will not require a shutdown.
    
    I do see a scenario where sequence of events can lead to loss of sequence
    and generate duplicate sequence values, if subscriber starts consuming
    sequences while publisher is also consuming them. In such cases, subscriber
    shall not be allowed sequence consumption.
    
    
    
    -- 
    Kind Regards,
    Yogesh Sharma
    Open Source Enthusiast and Advocate
    PostgreSQL Contributors Team @ RDS Open Source Databases
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
    
  6. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-05T03:15:27Z

    On Tue, Jun 4, 2024 at 7:40 PM Ashutosh Bapat
    <ashutosh.bapat.oss@gmail.com> wrote:
    >
    > On Tue, Jun 4, 2024 at 4:27 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >>
    >>
    >> 3. Replicate published sequences via walsender at the time of shutdown
    >> or incrementally while decoding checkpoint record. The two ways to
    >> achieve this are: (a) WAL log a special NOOP record just before
    >> shutting down checkpointer. Then allow the WALsender to read the
    >> sequence data and send it to the subscriber while decoding the new
    >> NOOP record. (b) Similar to the previous idea but instead of WAL
    >> logging a new record directly invokes a decoding callback after
    >> walsender receives a request to shutdown which will allow pgoutput to
    >> read and send required sequences. This approach has a drawback that we
    >> are adding more work at the time of shutdown but note that we already
    >> waits for all the WAL records to be decoded and sent before shutting
    >> down the walsender during shutdown of the node.
    >>
    >> Any other ideas?
    >>
    >
    > In case of primary crash the sequence won't get replicated. That is true even with the previous approach in case walsender is shut down because of a crash, but it is more serious with this approach.
    >
    
    Right, but if we just want to support a major version upgrade scenario
    then this should be fine because upgrades require a clean shutdown.
    
    >
     How about periodically sending this information?
    >
    
    Now, if we want to support some sort of failover then probably this
    will help. Do you have that use case in mind? If we want to send
    periodically then we can do it when decoding checkpoint
    (XLOG_CHECKPOINT_ONLINE) or some other periodic WAL record like
    running_xacts (XLOG_RUNNING_XACTS).
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  7. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-05T03:43:26Z

    On Tue, Jun 4, 2024 at 8:56 PM Yogesh Sharma
    <yogesh.sharma@catprosystems.com> wrote:
    >
    > On 6/4/24 06:57, Amit Kapila wrote:
    >
    > > 2. Provide a command say Alter Subscription ...  Replicate Sequences
    > > (or something like that) which users can perform before shutdown of
    > > the publisher node during upgrade. This will allow copying all the
    > > sequences from the publisher node to the subscriber node directly.
    > > Similar to previous approach, this could also be inconvenient for
    > > users.
    >
    > This is similar to option 1 except that it is a SQL command now.
    >
    
    Right, but I would still prefer a command as it provides clear steps
    for the upgrade. Users need to perform (a) Replicate Sequences for a
    particular subscription (b) Disable that subscription (c) Perform (a)
    and (b) for all the subscriptions corresponding to the publisher we
    want to shut down for upgrade.
    
    I agree there are some manual steps involved here but it is advisable
    for users to ensure that they have received the required data on the
    subscriber before the upgrade of the publisher node, otherwise, they
    may not be able to continue replication after the upgrade. For
    example, see the "Prepare for publisher upgrades" step in pg_upgrade
    docs [1].
    
    >
    > > 3. Replicate published sequences via walsender at the time of shutdown
    > > or incrementally while decoding checkpoint record. The two ways to
    > > achieve this are: (a) WAL log a special NOOP record just before
    > > shutting down checkpointer. Then allow the WALsender to read the
    > > sequence data and send it to the subscriber while decoding the new
    > > NOOP record. (b) Similar to the previous idea but instead of WAL
    > > logging a new record directly invokes a decoding callback after
    > > walsender receives a request to shutdown which will allow pgoutput to
    > > read and send required sequences. This approach has a drawback that we
    > > are adding more work at the time of shutdown but note that we already
    > > waits for all the WAL records to be decoded and sent before shutting
    > > down the walsender during shutdown of the node.
    >
    > At the time of shutdown a) most logical upgrades don't necessarily call
    > for shutdown
    >
    
    Won't the major version upgrade expect that the node is down? Refer to
    step "Stop both servers" in [1].
    
    >
     b) it will still add to total downtime with large set of
    > sequences. Incremental option is better as it will not require a shutdown.
    >
    > I do see a scenario where sequence of events can lead to loss of sequence
    > and generate duplicate sequence values, if subscriber starts consuming
    > sequences while publisher is also consuming them. In such cases, subscriber
    > shall not be allowed sequence consumption.
    >
    
    It would be fine to not allow subscribers to consume sequences that
    are being logically replicated but what about the cases where we
    haven't sent the latest values of sequences before the shutdown of the
    publisher? In such a case, the publisher would have already consumed
    some values that wouldn't have been sent to the subscriber and now
    when the publisher is down then even if we re-allow the sequence
    values to be consumed from the subscriber, it can lead to duplicate
    values.
    
    [1] - https://www.postgresql.org/docs/devel/pgupgrade.html
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  8. Re: Logical Replication of sequences

    Peter Eisentraut <peter@eisentraut.org> — 2024-06-05T07:21:22Z

    On 04.06.24 12:57, Amit Kapila wrote:
    > 2. Provide a command say Alter Subscription ...  Replicate Sequences
    > (or something like that) which users can perform before shutdown of
    > the publisher node during upgrade. This will allow copying all the
    > sequences from the publisher node to the subscriber node directly.
    > Similar to previous approach, this could also be inconvenient for
    > users.
    
    I would start with this.  In any case, you're going to need to write 
    code to collect all the sequence values, send them over some protocol, 
    apply them on the subscriber.  The easiest way to start is to trigger 
    that manually.  Then later you can add other ways to trigger it, either 
    by timer or around shutdown, or whatever other ideas there might be.
    
    
    
    
  9. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-05T08:41:36Z

    On Wed, Jun 5, 2024 at 9:13 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Jun 4, 2024 at 8:56 PM Yogesh Sharma
    > <yogesh.sharma@catprosystems.com> wrote:
    > >
    > > On 6/4/24 06:57, Amit Kapila wrote:
    > >
    > > > 2. Provide a command say Alter Subscription ...  Replicate Sequences
    > > > (or something like that) which users can perform before shutdown of
    > > > the publisher node during upgrade. This will allow copying all the
    > > > sequences from the publisher node to the subscriber node directly.
    > > > Similar to previous approach, this could also be inconvenient for
    > > > users.
    > >
    > > This is similar to option 1 except that it is a SQL command now.
    > >
    >
    > Right, but I would still prefer a command as it provides clear steps
    > for the upgrade. Users need to perform (a) Replicate Sequences for a
    > particular subscription (b) Disable that subscription (c) Perform (a)
    > and (b) for all the subscriptions corresponding to the publisher we
    > want to shut down for upgrade.
    >
    
    Another advantage of this approach over just a plain tool to copy all
    sequences before upgrade is that here we can have the facility to copy
    just the required sequences. I mean the set sequences that the user
    has specified as part of the publication.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  10. Re: Logical Replication of sequences

    Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com> — 2024-06-05T09:47:24Z

    Hi,
    
    On Tue, Jun 4, 2024 at 5:40 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > Even if we decode it periodically (say each time we decode the
    > checkpoint record) then also we need to send the entire set of
    > sequences at shutdown. This is because the sequences may have changed
    > from the last time we sent them.
    
    Agree. How about decoding and sending only the sequences that are
    changed from the last time when they were sent? I know it requires a
    bit of tracking and more work, but all I'm looking for is to reduce
    the amount of work that walsenders need to do during the shutdown.
    
    Having said that, I like the idea of letting the user sync the
    sequences via ALTER SUBSCRIPTION command and not weave the logic into
    the shutdown checkpoint path. As Peter Eisentraut said here
    https://www.postgresql.org/message-id/42e5cb35-4aeb-4f58-8091-90619c7c3ecc%40eisentraut.org,
    this can be a good starting point to get going.
    
    > > I can imagine a case where there are tens
    > > of thousands of sequences in a production server, and surely decoding
    > > and sending them just during the shutdown can take a lot of time
    > > hampering the overall server uptime.
    >
    > It is possible but we will send only the sequences that belong to
    > publications for which walsender is supposed to send the required
    > data.
    
    Right, but what if all the publication tables can have tens of
    thousands of sequences.
    
    > Now, we can also imagine providing option 2 (Alter Subscription
    > ... Replicate Sequences) so that users can replicate sequences before
    > shutdown and then disable the subscriptions so that there won't be a
    > corresponding walsender.
    
    As stated above, I like this idea to start with.
    
    --
    Bharath Rupireddy
    PostgreSQL Contributors Team
    RDS Open Source Databases
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  11. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-05T12:30:38Z

    On Wed, Jun 5, 2024 at 12:51 PM Peter Eisentraut <peter@eisentraut.org> wrote:
    >
    > On 04.06.24 12:57, Amit Kapila wrote:
    > > 2. Provide a command say Alter Subscription ...  Replicate Sequences
    > > (or something like that) which users can perform before shutdown of
    > > the publisher node during upgrade. This will allow copying all the
    > > sequences from the publisher node to the subscriber node directly.
    > > Similar to previous approach, this could also be inconvenient for
    > > users.
    >
    > I would start with this.  In any case, you're going to need to write
    > code to collect all the sequence values, send them over some protocol,
    > apply them on the subscriber.  The easiest way to start is to trigger
    > that manually.  Then later you can add other ways to trigger it, either
    > by timer or around shutdown, or whatever other ideas there might be.
    >
    
    Agreed. To achieve this, we can allow sequences to be copied during
    the initial CREATE SUBSCRIPTION command similar to what we do for
    tables. And then later by new/existing command, we re-copy the already
    existing sequences on the subscriber.
    
    The options for the new command could be:
    Alter Subscription ... Refresh Sequences
    Alter Subscription ... Replicate Sequences
    
    In the second option, we need to introduce a new keyword Replicate.
    Can you think of any better option?
    
    In addition to the above, the command Alter Subscription .. Refresh
    Publication will fetch any missing sequences similar to what it does
    for tables.
    
    Thoughts?
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  12. Re: Logical Replication of sequences

    Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> — 2024-06-05T12:31:15Z

    On Wed, Jun 5, 2024 at 8:45 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    
    > On Tue, Jun 4, 2024 at 7:40 PM Ashutosh Bapat
    > <ashutosh.bapat.oss@gmail.com> wrote:
    > >
    > > On Tue, Jun 4, 2024 at 4:27 PM Amit Kapila <amit.kapila16@gmail.com>
    > wrote:
    > >>
    > >>
    > >> 3. Replicate published sequences via walsender at the time of shutdown
    > >> or incrementally while decoding checkpoint record. The two ways to
    > >> achieve this are: (a) WAL log a special NOOP record just before
    > >> shutting down checkpointer. Then allow the WALsender to read the
    > >> sequence data and send it to the subscriber while decoding the new
    > >> NOOP record. (b) Similar to the previous idea but instead of WAL
    > >> logging a new record directly invokes a decoding callback after
    > >> walsender receives a request to shutdown which will allow pgoutput to
    > >> read and send required sequences. This approach has a drawback that we
    > >> are adding more work at the time of shutdown but note that we already
    > >> waits for all the WAL records to be decoded and sent before shutting
    > >> down the walsender during shutdown of the node.
    > >>
    > >> Any other ideas?
    > >>
    > >
    > > In case of primary crash the sequence won't get replicated. That is true
    > even with the previous approach in case walsender is shut down because of a
    > crash, but it is more serious with this approach.
    > >
    >
    > Right, but if we just want to support a major version upgrade scenario
    > then this should be fine because upgrades require a clean shutdown.
    >
    > >
    >  How about periodically sending this information?
    > >
    >
    > Now, if we want to support some sort of failover then probably this
    > will help. Do you have that use case in mind?
    
    
    Regular failover was a goal for supporting logical replication of
    sequences. That might be more common than major upgrade scenario.
    
    
    > If we want to send
    > periodically then we can do it when decoding checkpoint
    > (XLOG_CHECKPOINT_ONLINE) or some other periodic WAL record like
    > running_xacts (XLOG_RUNNING_XACTS).
    >
    >
    Yeah. I am thinking along those lines.
    
    It must be noted, however, that none of those optional make sure that the
    replicated sequence's states are consistent with the replicated object
    state which use those sequences. E.g. table t1 uses sequence s1. By last
    sequence replication, as of time T1, let's say t1 had consumed values upto
    vl1 from s1. But later, by time T2, it consumed values upto vl2 which were
    not replicated but the changes to t1 by T2 were replicated. If failover
    happens at that point, INSERTs on t1 would fail because of duplicate keys
    (values between vl1 and vl2). Previous attempt to support logical sequence
    replication solved this problem by replicating a future state of sequences
    (current value +/- log count). Similarly, if the sequence was ALTERed
    between T1 and T2, the state of sequence on replica would be inconsistent
    with the state of t1. Failing over at this stage, might end t1 in an
    inconsistent state.
    
    -- 
    Best Wishes,
    Ashutosh Bapat
    
  13. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-06T03:52:26Z

    On Wed, Jun 5, 2024 at 6:01 PM Ashutosh Bapat
    <ashutosh.bapat.oss@gmail.com> wrote:
    >
    > On Wed, Jun 5, 2024 at 8:45 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >>
    >>  How about periodically sending this information?
    >> >
    >>
    >> Now, if we want to support some sort of failover then probably this
    >> will help. Do you have that use case in mind?
    >
    >
    > Regular failover was a goal for supporting logical replication of sequences. That might be more common than major upgrade scenario.
    >
    
    We can't support regular failovers to subscribers unless we can
    replicate/copy slots because the existing nodes connected to the
    current publisher/primary would expect that. It should be primarily
    useful for major version upgrades at this stage.
    
    >>
    >> If we want to send
    >> periodically then we can do it when decoding checkpoint
    >> (XLOG_CHECKPOINT_ONLINE) or some other periodic WAL record like
    >> running_xacts (XLOG_RUNNING_XACTS).
    >>
    >
    > Yeah. I am thinking along those lines.
    >
    > It must be noted, however, that none of those optional make sure that the replicated sequence's states are consistent with the replicated object state which use those sequences.
    >
    
    Right, I feel as others are advocating, it seems better to support it
    manually via command and then later we can extend it to do at shutdown
    or at some regular intervals. If we do that then we should be able to
    support major version upgrades and planned switchover.
    
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  14. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-06T04:01:42Z

    On Wed, Jun 5, 2024 at 12:43 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Jun 4, 2024 at 8:56 PM Yogesh Sharma
    > <yogesh.sharma@catprosystems.com> wrote:
    > >
    > > On 6/4/24 06:57, Amit Kapila wrote:
    > >
    > > > 2. Provide a command say Alter Subscription ...  Replicate Sequences
    > > > (or something like that) which users can perform before shutdown of
    > > > the publisher node during upgrade. This will allow copying all the
    > > > sequences from the publisher node to the subscriber node directly.
    > > > Similar to previous approach, this could also be inconvenient for
    > > > users.
    > >
    > > This is similar to option 1 except that it is a SQL command now.
    > >
    >
    > Right, but I would still prefer a command as it provides clear steps
    > for the upgrade. Users need to perform (a) Replicate Sequences for a
    > particular subscription (b) Disable that subscription (c) Perform (a)
    > and (b) for all the subscriptions corresponding to the publisher we
    > want to shut down for upgrade.
    >
    > I agree there are some manual steps involved here but it is advisable
    > for users to ensure that they have received the required data on the
    > subscriber before the upgrade of the publisher node, otherwise, they
    > may not be able to continue replication after the upgrade. For
    > example, see the "Prepare for publisher upgrades" step in pg_upgrade
    > docs [1].
    >
    > >
    > > > 3. Replicate published sequences via walsender at the time of shutdown
    > > > or incrementally while decoding checkpoint record. The two ways to
    > > > achieve this are: (a) WAL log a special NOOP record just before
    > > > shutting down checkpointer. Then allow the WALsender to read the
    > > > sequence data and send it to the subscriber while decoding the new
    > > > NOOP record. (b) Similar to the previous idea but instead of WAL
    > > > logging a new record directly invokes a decoding callback after
    > > > walsender receives a request to shutdown which will allow pgoutput to
    > > > read and send required sequences. This approach has a drawback that we
    > > > are adding more work at the time of shutdown but note that we already
    > > > waits for all the WAL records to be decoded and sent before shutting
    > > > down the walsender during shutdown of the node.
    > >
    > > At the time of shutdown a) most logical upgrades don't necessarily call
    > > for shutdown
    > >
    >
    > Won't the major version upgrade expect that the node is down? Refer to
    > step "Stop both servers" in [1].
    
    I think the idea is that the publisher is the old version and the
    subscriber is the new version, and changes generated on the publisher
    are replicated to the subscriber via logical replication. And at some
    point, we change the application (or a router) settings so that no
    more transactions come to the publisher, do the last upgrade
    preparation work (e.g. copying the latest sequence values if
    requried), and then change the application so that new transactions
    come to the subscriber.
    
    I remember the blog post about Knock doing a similar process to
    upgrade the clusters with minimal downtime[1].
    
    Regards,
    
    [1] https://knock.app/blog/zero-downtime-postgres-upgrades
    
    
    --
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  15. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-06T04:04:13Z

    On Wed, Jun 5, 2024 at 3:17 PM Bharath Rupireddy
    <bharath.rupireddyforpostgres@gmail.com> wrote:
    >
    > On Tue, Jun 4, 2024 at 5:40 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > Even if we decode it periodically (say each time we decode the
    > > checkpoint record) then also we need to send the entire set of
    > > sequences at shutdown. This is because the sequences may have changed
    > > from the last time we sent them.
    >
    > Agree. How about decoding and sending only the sequences that are
    > changed from the last time when they were sent? I know it requires a
    > bit of tracking and more work, but all I'm looking for is to reduce
    > the amount of work that walsenders need to do during the shutdown.
    >
    
    I see your point but going towards tracking the changed sequences
    sounds like moving towards what we do for incremental backups unless
    we can invent some other smart way.
    
    > Having said that, I like the idea of letting the user sync the
    > sequences via ALTER SUBSCRIPTION command and not weave the logic into
    > the shutdown checkpoint path. As Peter Eisentraut said here
    > https://www.postgresql.org/message-id/42e5cb35-4aeb-4f58-8091-90619c7c3ecc%40eisentraut.org,
    > this can be a good starting point to get going.
    >
    
    Agreed.
    
    > > > I can imagine a case where there are tens
    > > > of thousands of sequences in a production server, and surely decoding
    > > > and sending them just during the shutdown can take a lot of time
    > > > hampering the overall server uptime.
    > >
    > > It is possible but we will send only the sequences that belong to
    > > publications for which walsender is supposed to send the required
    > > data.
    >
    > Right, but what if all the publication tables can have tens of
    > thousands of sequences.
    >
    
    In such cases we have no option but to send all the sequences.
    
    > > Now, we can also imagine providing option 2 (Alter Subscription
    > > ... Replicate Sequences) so that users can replicate sequences before
    > > shutdown and then disable the subscriptions so that there won't be a
    > > corresponding walsender.
    >
    > As stated above, I like this idea to start with.
    >
    
    +1.
    
    
    --
    With Regards,
    Amit Kapila.
    
    
    
    
  16. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-06T05:39:45Z

    On Wed, Jun 5, 2024 at 9:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Wed, Jun 5, 2024 at 12:51 PM Peter Eisentraut <peter@eisentraut.org> wrote:
    > >
    > > On 04.06.24 12:57, Amit Kapila wrote:
    > > > 2. Provide a command say Alter Subscription ...  Replicate Sequences
    > > > (or something like that) which users can perform before shutdown of
    > > > the publisher node during upgrade. This will allow copying all the
    > > > sequences from the publisher node to the subscriber node directly.
    > > > Similar to previous approach, this could also be inconvenient for
    > > > users.
    > >
    > > I would start with this.  In any case, you're going to need to write
    > > code to collect all the sequence values, send them over some protocol,
    > > apply them on the subscriber.  The easiest way to start is to trigger
    > > that manually.  Then later you can add other ways to trigger it, either
    > > by timer or around shutdown, or whatever other ideas there might be.
    > >
    >
    > Agreed.
    
    +1
    
    > To achieve this, we can allow sequences to be copied during
    > the initial CREATE SUBSCRIPTION command similar to what we do for
    > tables. And then later by new/existing command, we re-copy the already
    > existing sequences on the subscriber.
    >
    > The options for the new command could be:
    > Alter Subscription ... Refresh Sequences
    > Alter Subscription ... Replicate Sequences
    >
    > In the second option, we need to introduce a new keyword Replicate.
    > Can you think of any better option?
    
    Another idea is doing that using options. For example,
    
    For initial sequences synchronization:
    
    CREATE SUBSCRIPTION ... WITH (copy_sequence = true);
    
    For re-copy (or update) sequences:
    
    ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH (copy_sequence = true);
    
    >
    > In addition to the above, the command Alter Subscription .. Refresh
    > Publication will fetch any missing sequences similar to what it does
    > for tables.
    
    On the subscriber side, do we need to track which sequences are
    created via CREATE/ALTER SUBSCRIPTION?
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  17. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-06T06:47:52Z

    On Thu, Jun 6, 2024 at 9:32 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Wed, Jun 5, 2024 at 12:43 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Tue, Jun 4, 2024 at 8:56 PM Yogesh Sharma
    > > <yogesh.sharma@catprosystems.com> wrote:
    > > >
    > > > On 6/4/24 06:57, Amit Kapila wrote:
    > > >
    > > > > 2. Provide a command say Alter Subscription ...  Replicate Sequences
    > > > > (or something like that) which users can perform before shutdown of
    > > > > the publisher node during upgrade. This will allow copying all the
    > > > > sequences from the publisher node to the subscriber node directly.
    > > > > Similar to previous approach, this could also be inconvenient for
    > > > > users.
    > > >
    > > > This is similar to option 1 except that it is a SQL command now.
    > > >
    > >
    > > Right, but I would still prefer a command as it provides clear steps
    > > for the upgrade. Users need to perform (a) Replicate Sequences for a
    > > particular subscription (b) Disable that subscription (c) Perform (a)
    > > and (b) for all the subscriptions corresponding to the publisher we
    > > want to shut down for upgrade.
    > >
    > > I agree there are some manual steps involved here but it is advisable
    > > for users to ensure that they have received the required data on the
    > > subscriber before the upgrade of the publisher node, otherwise, they
    > > may not be able to continue replication after the upgrade. For
    > > example, see the "Prepare for publisher upgrades" step in pg_upgrade
    > > docs [1].
    > >
    > > >
    > > > > 3. Replicate published sequences via walsender at the time of shutdown
    > > > > or incrementally while decoding checkpoint record. The two ways to
    > > > > achieve this are: (a) WAL log a special NOOP record just before
    > > > > shutting down checkpointer. Then allow the WALsender to read the
    > > > > sequence data and send it to the subscriber while decoding the new
    > > > > NOOP record. (b) Similar to the previous idea but instead of WAL
    > > > > logging a new record directly invokes a decoding callback after
    > > > > walsender receives a request to shutdown which will allow pgoutput to
    > > > > read and send required sequences. This approach has a drawback that we
    > > > > are adding more work at the time of shutdown but note that we already
    > > > > waits for all the WAL records to be decoded and sent before shutting
    > > > > down the walsender during shutdown of the node.
    > > >
    > > > At the time of shutdown a) most logical upgrades don't necessarily call
    > > > for shutdown
    > > >
    > >
    > > Won't the major version upgrade expect that the node is down? Refer to
    > > step "Stop both servers" in [1].
    >
    > I think the idea is that the publisher is the old version and the
    > subscriber is the new version, and changes generated on the publisher
    > are replicated to the subscriber via logical replication. And at some
    > point, we change the application (or a router) settings so that no
    > more transactions come to the publisher, do the last upgrade
    > preparation work (e.g. copying the latest sequence values if
    > requried), and then change the application so that new transactions
    > come to the subscriber.
    >
    
    Okay, thanks for sharing the exact steps. If one has to follow that
    path then sending incrementally (at checkpoint WAL or other times)
    won't work because we want to ensure that the sequences are up-to-date
    before the application starts using the new database. To do that in a
    bullet-proof way, one has to copy/replicate sequences during the
    requests to the new database are paused (Reference from the blog you
    shared: For the first second after flipping the flag, our application
    artificially paused any new database requests for one second.).
    Currently, they are using some guesswork to replicate sequences that
    require manual verification and more manual work for each sequence.
    The new command (Alter Subscription ... Replicate Sequence) should
    ease their procedure and can do things where they would require no or
    very less verification.
    
    > I remember the blog post about Knock doing a similar process to
    > upgrade the clusters with minimal downtime[1].
    >
    
    Thanks for sharing the blog post.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  18. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-06T09:40:06Z

    On Thu, Jun 6, 2024 at 11:10 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Wed, Jun 5, 2024 at 9:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    >
    > > To achieve this, we can allow sequences to be copied during
    > > the initial CREATE SUBSCRIPTION command similar to what we do for
    > > tables. And then later by new/existing command, we re-copy the already
    > > existing sequences on the subscriber.
    > >
    > > The options for the new command could be:
    > > Alter Subscription ... Refresh Sequences
    > > Alter Subscription ... Replicate Sequences
    > >
    > > In the second option, we need to introduce a new keyword Replicate.
    > > Can you think of any better option?
    >
    > Another idea is doing that using options. For example,
    >
    > For initial sequences synchronization:
    >
    > CREATE SUBSCRIPTION ... WITH (copy_sequence = true);
    >
    
    How will it interact with the existing copy_data option? So copy_data
    will become equivalent to copy_table_data, right?
    
    > For re-copy (or update) sequences:
    >
    > ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH (copy_sequence = true);
    >
    
    Similar to the previous point it can be slightly confusing w.r.t
    copy_data. And would copy_sequence here mean that it would copy
    sequence values of both pre-existing and newly added sequences, if so,
    that would make it behave differently than copy_data? The other
    possibility in this direction would be to introduce an option like
    replicate_all_sequences/copy_all_sequences which indicates a copy of
    both pre-existing and new sequences, if any.
    
    If we want to go in the direction of having an option such as
    copy_(all)_sequences then do you think specifying that copy_data is
    just for tables in the docs would be sufficient? I am afraid that it
    would be confusing for users.
    
    > >
    > > In addition to the above, the command Alter Subscription .. Refresh
    > > Publication will fetch any missing sequences similar to what it does
    > > for tables.
    >
    > On the subscriber side, do we need to track which sequences are
    > created via CREATE/ALTER SUBSCRIPTION?
    >
    
    I think so unless we find some other way to know at refresh
    publication time which all new sequences need to be part of the
    subscription. What should be the behavior w.r.t sequences when the
    user performs ALTER SUBSCRIPTION ... REFRESH PUBLICATION? I was
    thinking similar to tables, it should fetch any missing sequence
    information from the publisher.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  19. Re: Logical Replication of sequences

    Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> — 2024-06-06T10:13:53Z

    On Thu, Jun 6, 2024 at 9:22 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    
    > On Wed, Jun 5, 2024 at 6:01 PM Ashutosh Bapat
    > <ashutosh.bapat.oss@gmail.com> wrote:
    > >
    > > On Wed, Jun 5, 2024 at 8:45 AM Amit Kapila <amit.kapila16@gmail.com>
    > wrote:
    > >>
    > >>  How about periodically sending this information?
    > >> >
    > >>
    > >> Now, if we want to support some sort of failover then probably this
    > >> will help. Do you have that use case in mind?
    > >
    > >
    > > Regular failover was a goal for supporting logical replication of
    > sequences. That might be more common than major upgrade scenario.
    > >
    >
    > We can't support regular failovers to subscribers unless we can
    > replicate/copy slots because the existing nodes connected to the
    > current publisher/primary would expect that. It should be primarily
    > useful for major version upgrades at this stage.
    >
    
    We don't want to design it in a way that requires major rework when we are
    able to copy slots and then support regular failovers. That's when the
    consistency between a sequence and the table using it would be a must. So
    it's better that we take that into consideration now.
    
    -- 
    Best Wishes,
    Ashutosh Bapat
    
  20. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-06T11:00:51Z

    On Thu, Jun 6, 2024 at 3:44 PM Ashutosh Bapat
    <ashutosh.bapat.oss@gmail.com> wrote:
    >
    > On Thu, Jun 6, 2024 at 9:22 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >>
    >> On Wed, Jun 5, 2024 at 6:01 PM Ashutosh Bapat
    >> <ashutosh.bapat.oss@gmail.com> wrote:
    >> >
    >> > On Wed, Jun 5, 2024 at 8:45 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >> >>
    >> >>  How about periodically sending this information?
    >> >> >
    >> >>
    >> >> Now, if we want to support some sort of failover then probably this
    >> >> will help. Do you have that use case in mind?
    >> >
    >> >
    >> > Regular failover was a goal for supporting logical replication of sequences. That might be more common than major upgrade scenario.
    >> >
    >>
    >> We can't support regular failovers to subscribers unless we can
    >> replicate/copy slots because the existing nodes connected to the
    >> current publisher/primary would expect that. It should be primarily
    >> useful for major version upgrades at this stage.
    >
    >
    > We don't want to design it in a way that requires major rework when we are able to copy slots and then support regular failover.
    >
    
    I don't think we can just copy slots like we do for standbys. The
    slots would require WAL locations to continue, so not sure if we can
    make it work for failover for subscribers.
    
    >
     That's when the consistency between a sequence and the table using it
    would be a must. So it's better that we take that into consideration
    now.
    >
    
    With the ideas being discussed here, I could only see the use case of
    a major version upgrade or planned switchover to work. If we come up
    with any other agreeable way that is better than this then we can
    consider the same.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  21. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2024-06-06T12:32:16Z

    On Thu, Jun 6, 2024 at 9:34 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Wed, Jun 5, 2024 at 3:17 PM Bharath Rupireddy
    > <bharath.rupireddyforpostgres@gmail.com> wrote:
    > >
    > > On Tue, Jun 4, 2024 at 5:40 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > Even if we decode it periodically (say each time we decode the
    > > > checkpoint record) then also we need to send the entire set of
    > > > sequences at shutdown. This is because the sequences may have changed
    > > > from the last time we sent them.
    > >
    > > Agree. How about decoding and sending only the sequences that are
    > > changed from the last time when they were sent? I know it requires a
    > > bit of tracking and more work, but all I'm looking for is to reduce
    > > the amount of work that walsenders need to do during the shutdown.
    > >
    >
    > I see your point but going towards tracking the changed sequences
    > sounds like moving towards what we do for incremental backups unless
    > we can invent some other smart way.
    
    Yes, we would need an entirely new infrastructure to track the
    sequence change since the last sync. We can only determine this from
    WAL, and relying on it would somehow bring us back to the approach we
    were trying to achieve with logical decoding of sequences patch.
    
    > > Having said that, I like the idea of letting the user sync the
    > > sequences via ALTER SUBSCRIPTION command and not weave the logic into
    > > the shutdown checkpoint path. As Peter Eisentraut said here
    > > https://www.postgresql.org/message-id/42e5cb35-4aeb-4f58-8091-90619c7c3ecc%40eisentraut.org,
    > > this can be a good starting point to get going.
    > >
    >
    > Agreed.
    
    +1
    
    -- 
    Regards,
    Dilip Kumar
    EnterpriseDB: http://www.enterprisedb.com
    
    
    
    
  22. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-07T02:25:17Z

    On Thu, Jun 6, 2024 at 6:40 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Jun 6, 2024 at 11:10 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Wed, Jun 5, 2024 at 9:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > >
    > > > To achieve this, we can allow sequences to be copied during
    > > > the initial CREATE SUBSCRIPTION command similar to what we do for
    > > > tables. And then later by new/existing command, we re-copy the already
    > > > existing sequences on the subscriber.
    > > >
    > > > The options for the new command could be:
    > > > Alter Subscription ... Refresh Sequences
    > > > Alter Subscription ... Replicate Sequences
    > > >
    > > > In the second option, we need to introduce a new keyword Replicate.
    > > > Can you think of any better option?
    > >
    > > Another idea is doing that using options. For example,
    > >
    > > For initial sequences synchronization:
    > >
    > > CREATE SUBSCRIPTION ... WITH (copy_sequence = true);
    > >
    >
    > How will it interact with the existing copy_data option? So copy_data
    > will become equivalent to copy_table_data, right?
    
    Right.
    
    >
    > > For re-copy (or update) sequences:
    > >
    > > ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH (copy_sequence = true);
    > >
    >
    > Similar to the previous point it can be slightly confusing w.r.t
    > copy_data. And would copy_sequence here mean that it would copy
    > sequence values of both pre-existing and newly added sequences, if so,
    > that would make it behave differently than copy_data?  The other
    > possibility in this direction would be to introduce an option like
    > replicate_all_sequences/copy_all_sequences which indicates a copy of
    > both pre-existing and new sequences, if any.
    
    Copying sequence data works differently than replicating table data
    (initial data copy and logical replication). So I thought the
    copy_sequence option (or whatever better name) always does both
    updating pre-existing sequences and adding new sequences. REFRESH
    PUBLICATION updates the tables to be subscribed, so we also update or
    add sequences associated to these tables.
    
    >
    > If we want to go in the direction of having an option such as
    > copy_(all)_sequences then do you think specifying that copy_data is
    > just for tables in the docs would be sufficient? I am afraid that it
    > would be confusing for users.
    
    I see your point. But I guess it would not be very problematic as it
    doesn't break the current behavior and copy_(all)_sequences is
    primarily for upgrade use cases.
    
    >
    > > >
    > > > In addition to the above, the command Alter Subscription .. Refresh
    > > > Publication will fetch any missing sequences similar to what it does
    > > > for tables.
    > >
    > > On the subscriber side, do we need to track which sequences are
    > > created via CREATE/ALTER SUBSCRIPTION?
    > >
    >
    > I think so unless we find some other way to know at refresh
    > publication time which all new sequences need to be part of the
    > subscription. What should be the behavior w.r.t sequences when the
    > user performs ALTER SUBSCRIPTION ... REFRESH PUBLICATION? I was
    > thinking similar to tables, it should fetch any missing sequence
    > information from the publisher.
    
    It seems to make sense to me. But I have one question: do we want to
    support replicating sequences that are not associated with any tables?
    if yes, what if we refresh two different subscriptions that subscribe
    to different tables on the same database? On the other hand, if no
    (i.e. replicating only sequences owned by tables), can we know which
    sequences to replicate by checking the subscribed tables?
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  23. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-07T10:29:53Z

    On Fri, Jun 7, 2024 at 7:55 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Thu, Jun 6, 2024 at 6:40 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Thu, Jun 6, 2024 at 11:10 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > >
    > > > On Wed, Jun 5, 2024 at 9:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > >
    > > > > To achieve this, we can allow sequences to be copied during
    > > > > the initial CREATE SUBSCRIPTION command similar to what we do for
    > > > > tables. And then later by new/existing command, we re-copy the already
    > > > > existing sequences on the subscriber.
    > > > >
    > > > > The options for the new command could be:
    > > > > Alter Subscription ... Refresh Sequences
    > > > > Alter Subscription ... Replicate Sequences
    > > > >
    > > > > In the second option, we need to introduce a new keyword Replicate.
    > > > > Can you think of any better option?
    > > >
    > > > Another idea is doing that using options. For example,
    > > >
    > > > For initial sequences synchronization:
    > > >
    > > > CREATE SUBSCRIPTION ... WITH (copy_sequence = true);
    > > >
    > >
    > > How will it interact with the existing copy_data option? So copy_data
    > > will become equivalent to copy_table_data, right?
    >
    > Right.
    >
    > >
    > > > For re-copy (or update) sequences:
    > > >
    > > > ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH (copy_sequence = true);
    > > >
    > >
    > > Similar to the previous point it can be slightly confusing w.r.t
    > > copy_data. And would copy_sequence here mean that it would copy
    > > sequence values of both pre-existing and newly added sequences, if so,
    > > that would make it behave differently than copy_data?  The other
    > > possibility in this direction would be to introduce an option like
    > > replicate_all_sequences/copy_all_sequences which indicates a copy of
    > > both pre-existing and new sequences, if any.
    >
    > Copying sequence data works differently than replicating table data
    > (initial data copy and logical replication). So I thought the
    > copy_sequence option (or whatever better name) always does both
    > updating pre-existing sequences and adding new sequences. REFRESH
    > PUBLICATION updates the tables to be subscribed, so we also update or
    > add sequences associated to these tables.
    >
    
    Are you imagining the behavior for sequences associated with tables
    differently than the ones defined by the CREATE SEQUENCE .. command? I
    was thinking that users would associate sequences with publications
    similar to what we do for tables for both cases. For example, they
    need to explicitly mention the sequences they want to replicate by
    commands like CREATE PUBLICATION ... FOR SEQUENCE s1, s2, ...; CREATE
    PUBLICATION ... FOR ALL SEQUENCES, or CREATE PUBLICATION ... FOR
    SEQUENCES IN SCHEMA sch1;
    
    In this, variants FOR ALL SEQUENCES and SEQUENCES IN SCHEMA sch1
    should copy both the explicitly defined sequences and sequences
    defined with the tables. Do you think a different variant for just
    copying sequences implicitly associated with tables (say for identity
    columns)?
    
    >
    > >
    > > > >
    > > > > In addition to the above, the command Alter Subscription .. Refresh
    > > > > Publication will fetch any missing sequences similar to what it does
    > > > > for tables.
    > > >
    > > > On the subscriber side, do we need to track which sequences are
    > > > created via CREATE/ALTER SUBSCRIPTION?
    > > >
    > >
    > > I think so unless we find some other way to know at refresh
    > > publication time which all new sequences need to be part of the
    > > subscription. What should be the behavior w.r.t sequences when the
    > > user performs ALTER SUBSCRIPTION ... REFRESH PUBLICATION? I was
    > > thinking similar to tables, it should fetch any missing sequence
    > > information from the publisher.
    >
    > It seems to make sense to me. But I have one question: do we want to
    > support replicating sequences that are not associated with any tables?
    >
    
    Yes, unless we see a problem with it.
    
    > if yes, what if we refresh two different subscriptions that subscribe
    > to different tables on the same database?
    
    What problem do you see with it?
    
    >
     On the other hand, if no
    > (i.e. replicating only sequences owned by tables), can we know which
    > sequences to replicate by checking the subscribed tables?
    >
    
    Sorry, I didn't understand your question. Can you please try to
    explain in more words or use some examples?
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  24. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-08T13:13:32Z

    On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Wed, Jun 5, 2024 at 9:13 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Tue, Jun 4, 2024 at 8:56 PM Yogesh Sharma
    > > <yogesh.sharma@catprosystems.com> wrote:
    > > >
    > > > On 6/4/24 06:57, Amit Kapila wrote:
    > > >
    > > > > 2. Provide a command say Alter Subscription ...  Replicate Sequences
    > > > > (or something like that) which users can perform before shutdown of
    > > > > the publisher node during upgrade. This will allow copying all the
    > > > > sequences from the publisher node to the subscriber node directly.
    > > > > Similar to previous approach, this could also be inconvenient for
    > > > > users.
    > > >
    > > > This is similar to option 1 except that it is a SQL command now.
    > > >
    > >
    > > Right, but I would still prefer a command as it provides clear steps
    > > for the upgrade. Users need to perform (a) Replicate Sequences for a
    > > particular subscription (b) Disable that subscription (c) Perform (a)
    > > and (b) for all the subscriptions corresponding to the publisher we
    > > want to shut down for upgrade.
    > >
    >
    > Another advantage of this approach over just a plain tool to copy all
    > sequences before upgrade is that here we can have the facility to copy
    > just the required sequences. I mean the set sequences that the user
    > has specified as part of the publication.
    
    Here is a WIP patch to handle synchronizing the sequence during
    create/alter subscription. The following changes were made for it:
    Subscriber modifications:
    Enable sequence synchronization during subscription creation or
    alteration using the following syntax:
    CREATE SUBSCRIPTION ... WITH (sequences=true);
    When a subscription is created with the sequence option enabled, the
    sequence list from the specified publications in the subscription will
    be retrieved from the publisher. Each sequence's data will then be
    copied from the remote publisher sequence to the local subscriber
    sequence by using a wal receiver connection. Since all of the sequence
    updating is done within a single transaction, if any errors occur
    during the copying process, the entire transaction will be rolled
    back.
    
    To refresh sequences, use the syntax:
    ALTER SUBSCRIPTION REFRESH SEQUENCES;
    During sequence refresh, the sequence list is updated by removing
    stale sequences and adding any missing sequences. The updated sequence
    list is then re-synchronized.
    
    A new catalog table, pg_subscription_seq, has been introduced for
    mapping subscriptions to sequences. Additionally, the sequence LSN
    (Log Sequence Number) is stored, facilitating determination of
    sequence changes occurring before or after the returned sequence
    state.
    
    I have taken some code changes from Tomas's patch at [1].
    I'll adjust the syntax as needed based on the ongoing discussion at  [2].
    
    [1] - https://www.postgresql.org/message-id/09613730-5ee9-4cc3-82d8-f089be90aa64%40enterprisedb.com
    [2] - https://www.postgresql.org/message-id/CAA4eK1K2X%2BPaErtGVQPD0k_5XqxjV_Cwg37%2B-pWsmKFncwc7Wg%40mail.gmail.com
    
    Regards,
    Vignesh
    
  25. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-10T06:14:23Z

    On Fri, Jun 7, 2024 at 7:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Fri, Jun 7, 2024 at 7:55 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Thu, Jun 6, 2024 at 6:40 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Thu, Jun 6, 2024 at 11:10 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > > >
    > > > > On Wed, Jun 5, 2024 at 9:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > >
    > > > >
    > > > > > To achieve this, we can allow sequences to be copied during
    > > > > > the initial CREATE SUBSCRIPTION command similar to what we do for
    > > > > > tables. And then later by new/existing command, we re-copy the already
    > > > > > existing sequences on the subscriber.
    > > > > >
    > > > > > The options for the new command could be:
    > > > > > Alter Subscription ... Refresh Sequences
    > > > > > Alter Subscription ... Replicate Sequences
    > > > > >
    > > > > > In the second option, we need to introduce a new keyword Replicate.
    > > > > > Can you think of any better option?
    > > > >
    > > > > Another idea is doing that using options. For example,
    > > > >
    > > > > For initial sequences synchronization:
    > > > >
    > > > > CREATE SUBSCRIPTION ... WITH (copy_sequence = true);
    > > > >
    > > >
    > > > How will it interact with the existing copy_data option? So copy_data
    > > > will become equivalent to copy_table_data, right?
    > >
    > > Right.
    > >
    > > >
    > > > > For re-copy (or update) sequences:
    > > > >
    > > > > ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH (copy_sequence = true);
    > > > >
    > > >
    > > > Similar to the previous point it can be slightly confusing w.r.t
    > > > copy_data. And would copy_sequence here mean that it would copy
    > > > sequence values of both pre-existing and newly added sequences, if so,
    > > > that would make it behave differently than copy_data?  The other
    > > > possibility in this direction would be to introduce an option like
    > > > replicate_all_sequences/copy_all_sequences which indicates a copy of
    > > > both pre-existing and new sequences, if any.
    > >
    > > Copying sequence data works differently than replicating table data
    > > (initial data copy and logical replication). So I thought the
    > > copy_sequence option (or whatever better name) always does both
    > > updating pre-existing sequences and adding new sequences. REFRESH
    > > PUBLICATION updates the tables to be subscribed, so we also update or
    > > add sequences associated to these tables.
    > >
    >
    > Are you imagining the behavior for sequences associated with tables
    > differently than the ones defined by the CREATE SEQUENCE .. command? I
    > was thinking that users would associate sequences with publications
    > similar to what we do for tables for both cases. For example, they
    > need to explicitly mention the sequences they want to replicate by
    > commands like CREATE PUBLICATION ... FOR SEQUENCE s1, s2, ...; CREATE
    > PUBLICATION ... FOR ALL SEQUENCES, or CREATE PUBLICATION ... FOR
    > SEQUENCES IN SCHEMA sch1;
    >
    > In this, variants FOR ALL SEQUENCES and SEQUENCES IN SCHEMA sch1
    > should copy both the explicitly defined sequences and sequences
    > defined with the tables. Do you think a different variant for just
    > copying sequences implicitly associated with tables (say for identity
    > columns)?
    
    Oh, I was thinking that your proposal was to copy literally all
    sequences by REPLICA/REFRESH SEQUENCE command. But it seems to make
    sense to explicitly specify the sequences they want to replicate. It
    also means that they can create a publication that has only sequences.
    In this case, even if they create a subscription for that publication,
    we don't launch any apply workers for that subscription. Right?
    
    Also, given that the main use case (at least as the first step) is
    version upgrade, do we really need to support SEQUENCES IN SCHEMA and
    even FOR SEQUENCE? The WIP patch Vignesh recently submitted is more
    than 6k lines. I think we can cut the scope for the first
    implementation so as to make the review easy.
    
    Regards,
    
    --
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  26. Re: Logical Replication of sequences

    amul sul <sulamul@gmail.com> — 2024-06-10T06:54:04Z

    On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    
    > On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > [...]
    > A new catalog table, pg_subscription_seq, has been introduced for
    > mapping subscriptions to sequences. Additionally, the sequence LSN
    > (Log Sequence Number) is stored, facilitating determination of
    > sequence changes occurring before or after the returned sequence
    > state.
    >
    
    Can't it be done using pg_depend? It seems a bit excessive unless I'm
    missing
    something. How do you track sequence mapping with the publication?
    
    Regards,
    Amul
    
  27. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-10T07:12:42Z

    On Mon, Jun 10, 2024 at 3:14 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Fri, Jun 7, 2024 at 7:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Fri, Jun 7, 2024 at 7:55 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > >
    > > > On Thu, Jun 6, 2024 at 6:40 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > > > On Thu, Jun 6, 2024 at 11:10 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > > > >
    > > > > > On Wed, Jun 5, 2024 at 9:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > >
    > > > > >
    > > > > > > To achieve this, we can allow sequences to be copied during
    > > > > > > the initial CREATE SUBSCRIPTION command similar to what we do for
    > > > > > > tables. And then later by new/existing command, we re-copy the already
    > > > > > > existing sequences on the subscriber.
    > > > > > >
    > > > > > > The options for the new command could be:
    > > > > > > Alter Subscription ... Refresh Sequences
    > > > > > > Alter Subscription ... Replicate Sequences
    > > > > > >
    > > > > > > In the second option, we need to introduce a new keyword Replicate.
    > > > > > > Can you think of any better option?
    > > > > >
    > > > > > Another idea is doing that using options. For example,
    > > > > >
    > > > > > For initial sequences synchronization:
    > > > > >
    > > > > > CREATE SUBSCRIPTION ... WITH (copy_sequence = true);
    > > > > >
    > > > >
    > > > > How will it interact with the existing copy_data option? So copy_data
    > > > > will become equivalent to copy_table_data, right?
    > > >
    > > > Right.
    > > >
    > > > >
    > > > > > For re-copy (or update) sequences:
    > > > > >
    > > > > > ALTER SUBSCRIPTION ... REFRESH PUBLICATION WITH (copy_sequence = true);
    > > > > >
    > > > >
    > > > > Similar to the previous point it can be slightly confusing w.r.t
    > > > > copy_data. And would copy_sequence here mean that it would copy
    > > > > sequence values of both pre-existing and newly added sequences, if so,
    > > > > that would make it behave differently than copy_data?  The other
    > > > > possibility in this direction would be to introduce an option like
    > > > > replicate_all_sequences/copy_all_sequences which indicates a copy of
    > > > > both pre-existing and new sequences, if any.
    > > >
    > > > Copying sequence data works differently than replicating table data
    > > > (initial data copy and logical replication). So I thought the
    > > > copy_sequence option (or whatever better name) always does both
    > > > updating pre-existing sequences and adding new sequences. REFRESH
    > > > PUBLICATION updates the tables to be subscribed, so we also update or
    > > > add sequences associated to these tables.
    > > >
    > >
    > > Are you imagining the behavior for sequences associated with tables
    > > differently than the ones defined by the CREATE SEQUENCE .. command? I
    > > was thinking that users would associate sequences with publications
    > > similar to what we do for tables for both cases. For example, they
    > > need to explicitly mention the sequences they want to replicate by
    > > commands like CREATE PUBLICATION ... FOR SEQUENCE s1, s2, ...; CREATE
    > > PUBLICATION ... FOR ALL SEQUENCES, or CREATE PUBLICATION ... FOR
    > > SEQUENCES IN SCHEMA sch1;
    > >
    > > In this, variants FOR ALL SEQUENCES and SEQUENCES IN SCHEMA sch1
    > > should copy both the explicitly defined sequences and sequences
    > > defined with the tables. Do you think a different variant for just
    > > copying sequences implicitly associated with tables (say for identity
    > > columns)?
    >
    > Oh, I was thinking that your proposal was to copy literally all
    > sequences by REPLICA/REFRESH SEQUENCE command. But it seems to make
    > sense to explicitly specify the sequences they want to replicate. It
    > also means that they can create a publication that has only sequences.
    > In this case, even if they create a subscription for that publication,
    > we don't launch any apply workers for that subscription. Right?
    >
    > Also, given that the main use case (at least as the first step) is
    > version upgrade, do we really need to support SEQUENCES IN SCHEMA and
    > even FOR SEQUENCE?
    
    Also, I guess that specifying individual sequences might not be easy
    to use for users in some cases. For sequences owned by a column of a
    table, users might want to specify them altogether, rather than
    separately. For example, CREATE PUBLICATION ... FOR TABLE tab1 WITH
    SEQUENCES means to add the table tab1 and its sequences to the
    publication. For other sequences (i.e., not owned by any tables),
    users might want to specify them individually.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  28. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-10T09:18:25Z

    On Mon, Jun 10, 2024 at 12:43 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Mon, Jun 10, 2024 at 3:14 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Fri, Jun 7, 2024 at 7:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > >
    > > > Are you imagining the behavior for sequences associated with tables
    > > > differently than the ones defined by the CREATE SEQUENCE .. command? I
    > > > was thinking that users would associate sequences with publications
    > > > similar to what we do for tables for both cases. For example, they
    > > > need to explicitly mention the sequences they want to replicate by
    > > > commands like CREATE PUBLICATION ... FOR SEQUENCE s1, s2, ...; CREATE
    > > > PUBLICATION ... FOR ALL SEQUENCES, or CREATE PUBLICATION ... FOR
    > > > SEQUENCES IN SCHEMA sch1;
    > > >
    > > > In this, variants FOR ALL SEQUENCES and SEQUENCES IN SCHEMA sch1
    > > > should copy both the explicitly defined sequences and sequences
    > > > defined with the tables. Do you think a different variant for just
    > > > copying sequences implicitly associated with tables (say for identity
    > > > columns)?
    > >
    > > Oh, I was thinking that your proposal was to copy literally all
    > > sequences by REPLICA/REFRESH SEQUENCE command.
    > >
    
    I am trying to keep the behavior as close to tables as possible.
    
    > > But it seems to make
    > > sense to explicitly specify the sequences they want to replicate. It
    > > also means that they can create a publication that has only sequences.
    > > In this case, even if they create a subscription for that publication,
    > > we don't launch any apply workers for that subscription. Right?
    > >
    
    Right, good point. I had not thought about this.
    
    > > Also, given that the main use case (at least as the first step) is
    > > version upgrade, do we really need to support SEQUENCES IN SCHEMA and
    > > even FOR SEQUENCE?
    >
    
    At the very least, we can split the patch to move these variants to a
    separate patch. Once the main patch is finalized, we can try to
    evaluate the remaining separately.
    
    > Also, I guess that specifying individual sequences might not be easy
    > to use for users in some cases. For sequences owned by a column of a
    > table, users might want to specify them altogether, rather than
    > separately. For example, CREATE PUBLICATION ... FOR TABLE tab1 WITH
    > SEQUENCES means to add the table tab1 and its sequences to the
    > publication. For other sequences (i.e., not owned by any tables),
    > users might want to specify them individually.
    >
    
    Yeah, or we can have a syntax like CREATE PUBLICATION ... FOR TABLE
    tab1 INCLUDE SEQUENCES.  Normally, we use the WITH clause for options
    (For example, CREATE SUBSCRIPTION ... WITH (streaming=...)).
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  29. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-10T11:29:55Z

    On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    >
    >
    >
    > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    >>
    >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >> [...]
    >> A new catalog table, pg_subscription_seq, has been introduced for
    >> mapping subscriptions to sequences. Additionally, the sequence LSN
    >> (Log Sequence Number) is stored, facilitating determination of
    >> sequence changes occurring before or after the returned sequence
    >> state.
    >
    >
    > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    > something.
    
    We'll require the lsn because the sequence LSN informs the user that
    it has been synchronized up to the LSN in pg_subscription_seq. Since
    we are not supporting incremental sync, the user will be able to
    identify if he should run refresh sequences or not by checking the lsn
    of the pg_subscription_seq and the lsn of the sequence(using
    pg_sequence_state added) in the publisher.  Also, this parallels our
    implementation for pg_subscription_seq and will aid in expanding for
    a) incremental synchronization and b) utilizing workers for
    synchronization using sequence states if necessary.
    
    How do you track sequence mapping with the publication?
    
    In the publisher we use pg_publication_rel and
    pg_publication_namespace for mapping the sequences with the
    publication.
    
    Regards,
    Vignesh
    Vignesh
    
    
    
    
  30. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-11T03:25:14Z

    On Mon, 10 Jun 2024 at 14:48, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Mon, Jun 10, 2024 at 12:43 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Mon, Jun 10, 2024 at 3:14 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > >
    > > > On Fri, Jun 7, 2024 at 7:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > > >
    > > > > Are you imagining the behavior for sequences associated with tables
    > > > > differently than the ones defined by the CREATE SEQUENCE .. command? I
    > > > > was thinking that users would associate sequences with publications
    > > > > similar to what we do for tables for both cases. For example, they
    > > > > need to explicitly mention the sequences they want to replicate by
    > > > > commands like CREATE PUBLICATION ... FOR SEQUENCE s1, s2, ...; CREATE
    > > > > PUBLICATION ... FOR ALL SEQUENCES, or CREATE PUBLICATION ... FOR
    > > > > SEQUENCES IN SCHEMA sch1;
    > > > >
    > > > > In this, variants FOR ALL SEQUENCES and SEQUENCES IN SCHEMA sch1
    > > > > should copy both the explicitly defined sequences and sequences
    > > > > defined with the tables. Do you think a different variant for just
    > > > > copying sequences implicitly associated with tables (say for identity
    > > > > columns)?
    > > >
    > > > Oh, I was thinking that your proposal was to copy literally all
    > > > sequences by REPLICA/REFRESH SEQUENCE command.
    > > >
    >
    > I am trying to keep the behavior as close to tables as possible.
    >
    > > > But it seems to make
    > > > sense to explicitly specify the sequences they want to replicate. It
    > > > also means that they can create a publication that has only sequences.
    > > > In this case, even if they create a subscription for that publication,
    > > > we don't launch any apply workers for that subscription. Right?
    > > >
    >
    > Right, good point. I had not thought about this.
    >
    > > > Also, given that the main use case (at least as the first step) is
    > > > version upgrade, do we really need to support SEQUENCES IN SCHEMA and
    > > > even FOR SEQUENCE?
    > >
    >
    > At the very least, we can split the patch to move these variants to a
    > separate patch. Once the main patch is finalized, we can try to
    > evaluate the remaining separately.
    
    I engaged in an offline discussion with Amit about strategizing the
    division of patches to facilitate the review process. We agreed on the
    following split: The first patch will encompass the setting and
    getting of sequence values (core sequence changes). The second patch
    will cover all changes on the publisher side related to "FOR ALL
    SEQUENCES." The third patch will address subscriber side changes aimed
    at synchronizing "FOR ALL SEQUENCES" publications. The fourth patch
    will focus on supporting "FOR SEQUENCE" publication. Lastly, the fifth
    patch will introduce support for  "FOR ALL SEQUENCES IN SCHEMA"
    publication.
    
    I will work on this and share an updated patch for the same soon.
    
    Regards,
    Vignesh
    
    
    
    
  31. Re: Logical Replication of sequences

    amul sul <sulamul@gmail.com> — 2024-06-11T04:10:59Z

    On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    
    > On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    > >
    > >
    > >
    > > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    > >>
    > >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com>
    > wrote:
    > >> [...]
    > >> A new catalog table, pg_subscription_seq, has been introduced for
    > >> mapping subscriptions to sequences. Additionally, the sequence LSN
    > >> (Log Sequence Number) is stored, facilitating determination of
    > >> sequence changes occurring before or after the returned sequence
    > >> state.
    > >
    > >
    > > Can't it be done using pg_depend? It seems a bit excessive unless I'm
    > missing
    > > something.
    >
    > We'll require the lsn because the sequence LSN informs the user that
    > it has been synchronized up to the LSN in pg_subscription_seq. Since
    > we are not supporting incremental sync, the user will be able to
    > identify if he should run refresh sequences or not by checking the lsn
    > of the pg_subscription_seq and the lsn of the sequence(using
    > pg_sequence_state added) in the publisher.  Also, this parallels our
    > implementation for pg_subscription_seq and will aid in expanding for
    > a) incremental synchronization and b) utilizing workers for
    > synchronization using sequence states if necessary.
    >
    > How do you track sequence mapping with the publication?
    >
    > In the publisher we use pg_publication_rel and
    > pg_publication_namespace for mapping the sequences with the
    > publication.
    >
    
    Thanks for the explanation. I'm wondering what the complexity would be, if
    we
    wanted to do something similar on the subscriber side, i.e., tracking via
    pg_subscription_rel.
    
    Regards,
    Amul
    
  32. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-11T05:33:30Z

    On Tue, 11 Jun 2024 at 09:41, Amul Sul <sulamul@gmail.com> wrote:
    >
    > On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    >>
    >> On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    >> >
    >> >
    >> >
    >> > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    >> >>
    >> >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >> >> [...]
    >> >> A new catalog table, pg_subscription_seq, has been introduced for
    >> >> mapping subscriptions to sequences. Additionally, the sequence LSN
    >> >> (Log Sequence Number) is stored, facilitating determination of
    >> >> sequence changes occurring before or after the returned sequence
    >> >> state.
    >> >
    >> >
    >> > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    >> > something.
    >>
    >> We'll require the lsn because the sequence LSN informs the user that
    >> it has been synchronized up to the LSN in pg_subscription_seq. Since
    >> we are not supporting incremental sync, the user will be able to
    >> identify if he should run refresh sequences or not by checking the lsn
    >> of the pg_subscription_seq and the lsn of the sequence(using
    >> pg_sequence_state added) in the publisher.  Also, this parallels our
    >> implementation for pg_subscription_seq and will aid in expanding for
    >> a) incremental synchronization and b) utilizing workers for
    >> synchronization using sequence states if necessary.
    >>
    >> How do you track sequence mapping with the publication?
    >>
    >> In the publisher we use pg_publication_rel and
    >> pg_publication_namespace for mapping the sequences with the
    >> publication.
    >
    >
    > Thanks for the explanation. I'm wondering what the complexity would be, if we
    > wanted to do something similar on the subscriber side, i.e., tracking via
    > pg_subscription_rel.
    
    Because we won't utilize sync workers to synchronize the sequence, and
    the sequence won't necessitate sync states like init, sync,
    finishedcopy, syncdone, ready, etc., initially, I considered keeping
    the sequences separate. However, I'm ok with using pg_subscription_rel
    as it could potentially help in enhancing incremental synchronization
    and parallelizing later on.
    
    Regards,
    Vignesh
    
    
    
    
  33. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-11T07:08:08Z

    On Tue, Jun 11, 2024 at 12:25 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 10 Jun 2024 at 14:48, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Mon, Jun 10, 2024 at 12:43 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > >
    > > > On Mon, Jun 10, 2024 at 3:14 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > > >
    > > > > On Fri, Jun 7, 2024 at 7:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > >
    > > > > >
    > > > > > Are you imagining the behavior for sequences associated with tables
    > > > > > differently than the ones defined by the CREATE SEQUENCE .. command? I
    > > > > > was thinking that users would associate sequences with publications
    > > > > > similar to what we do for tables for both cases. For example, they
    > > > > > need to explicitly mention the sequences they want to replicate by
    > > > > > commands like CREATE PUBLICATION ... FOR SEQUENCE s1, s2, ...; CREATE
    > > > > > PUBLICATION ... FOR ALL SEQUENCES, or CREATE PUBLICATION ... FOR
    > > > > > SEQUENCES IN SCHEMA sch1;
    > > > > >
    > > > > > In this, variants FOR ALL SEQUENCES and SEQUENCES IN SCHEMA sch1
    > > > > > should copy both the explicitly defined sequences and sequences
    > > > > > defined with the tables. Do you think a different variant for just
    > > > > > copying sequences implicitly associated with tables (say for identity
    > > > > > columns)?
    > > > >
    > > > > Oh, I was thinking that your proposal was to copy literally all
    > > > > sequences by REPLICA/REFRESH SEQUENCE command.
    > > > >
    > >
    > > I am trying to keep the behavior as close to tables as possible.
    > >
    > > > > But it seems to make
    > > > > sense to explicitly specify the sequences they want to replicate. It
    > > > > also means that they can create a publication that has only sequences.
    > > > > In this case, even if they create a subscription for that publication,
    > > > > we don't launch any apply workers for that subscription. Right?
    > > > >
    > >
    > > Right, good point. I had not thought about this.
    > >
    > > > > Also, given that the main use case (at least as the first step) is
    > > > > version upgrade, do we really need to support SEQUENCES IN SCHEMA and
    > > > > even FOR SEQUENCE?
    > > >
    > >
    > > At the very least, we can split the patch to move these variants to a
    > > separate patch. Once the main patch is finalized, we can try to
    > > evaluate the remaining separately.
    >
    > I engaged in an offline discussion with Amit about strategizing the
    > division of patches to facilitate the review process. We agreed on the
    > following split: The first patch will encompass the setting and
    > getting of sequence values (core sequence changes). The second patch
    > will cover all changes on the publisher side related to "FOR ALL
    > SEQUENCES." The third patch will address subscriber side changes aimed
    > at synchronizing "FOR ALL SEQUENCES" publications. The fourth patch
    > will focus on supporting "FOR SEQUENCE" publication. Lastly, the fifth
    > patch will introduce support for  "FOR ALL SEQUENCES IN SCHEMA"
    > publication.
    >
    > I will work on this and share an updated patch for the same soon.
    
    +1. Sounds like a good plan.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  34. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-11T10:36:06Z

    On Tue, 11 Jun 2024 at 12:38, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Tue, Jun 11, 2024 at 12:25 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Mon, 10 Jun 2024 at 14:48, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Mon, Jun 10, 2024 at 12:43 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > > >
    > > > > On Mon, Jun 10, 2024 at 3:14 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > > > >
    > > > > > On Fri, Jun 7, 2024 at 7:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > >
    > > > > > >
    > > > > > > Are you imagining the behavior for sequences associated with tables
    > > > > > > differently than the ones defined by the CREATE SEQUENCE .. command? I
    > > > > > > was thinking that users would associate sequences with publications
    > > > > > > similar to what we do for tables for both cases. For example, they
    > > > > > > need to explicitly mention the sequences they want to replicate by
    > > > > > > commands like CREATE PUBLICATION ... FOR SEQUENCE s1, s2, ...; CREATE
    > > > > > > PUBLICATION ... FOR ALL SEQUENCES, or CREATE PUBLICATION ... FOR
    > > > > > > SEQUENCES IN SCHEMA sch1;
    > > > > > >
    > > > > > > In this, variants FOR ALL SEQUENCES and SEQUENCES IN SCHEMA sch1
    > > > > > > should copy both the explicitly defined sequences and sequences
    > > > > > > defined with the tables. Do you think a different variant for just
    > > > > > > copying sequences implicitly associated with tables (say for identity
    > > > > > > columns)?
    > > > > >
    > > > > > Oh, I was thinking that your proposal was to copy literally all
    > > > > > sequences by REPLICA/REFRESH SEQUENCE command.
    > > > > >
    > > >
    > > > I am trying to keep the behavior as close to tables as possible.
    > > >
    > > > > > But it seems to make
    > > > > > sense to explicitly specify the sequences they want to replicate. It
    > > > > > also means that they can create a publication that has only sequences.
    > > > > > In this case, even if they create a subscription for that publication,
    > > > > > we don't launch any apply workers for that subscription. Right?
    > > > > >
    > > >
    > > > Right, good point. I had not thought about this.
    > > >
    > > > > > Also, given that the main use case (at least as the first step) is
    > > > > > version upgrade, do we really need to support SEQUENCES IN SCHEMA and
    > > > > > even FOR SEQUENCE?
    > > > >
    > > >
    > > > At the very least, we can split the patch to move these variants to a
    > > > separate patch. Once the main patch is finalized, we can try to
    > > > evaluate the remaining separately.
    > >
    > > I engaged in an offline discussion with Amit about strategizing the
    > > division of patches to facilitate the review process. We agreed on the
    > > following split: The first patch will encompass the setting and
    > > getting of sequence values (core sequence changes). The second patch
    > > will cover all changes on the publisher side related to "FOR ALL
    > > SEQUENCES." The third patch will address subscriber side changes aimed
    > > at synchronizing "FOR ALL SEQUENCES" publications. The fourth patch
    > > will focus on supporting "FOR SEQUENCE" publication. Lastly, the fifth
    > > patch will introduce support for  "FOR ALL SEQUENCES IN SCHEMA"
    > > publication.
    > >
    > > I will work on this and share an updated patch for the same soon.
    >
    > +1. Sounds like a good plan.
    
    Amit and I engaged in an offline discussion regarding the design and
    contemplated that it could be like below:
    1) CREATE PUBLICATION syntax enhancement:
    CREATE PUBLICATION ... FOR ALL SEQUENCES;
    The addition of a new column titled "all sequences" in the
    pg_publication system table will signify whether the publication is
    designated as all sequences publication or not.
    
    2)  CREATE SUBSCRIPTION -- no syntax change.
    Upon creation of a subscription, the following additional steps will
    be managed by the subscriber:
    i) The subscriber will retrieve the list of sequences associated with
    the subscription's publications.
    ii) For each sequence: a) Retrieve the sequence value from the
    publisher by invoking the pg_sequence_state function. b) Set the
    sequence with the value obtained from the publisher. iv) Once the
    subscription creation is completed, all sequence values will become
    visible at the subscriber's end.
    
    An alternative design approach could involve retrieving the sequence
    list from the publisher during subscription creation and inserting the
    sequences with an "init" state into the pg_subscription_rel system
    table. These tasks could be executed by a single sequence sync worker,
    which would:
    i) Retrieve the list of sequences in the "init" state from the
    pg_subscription_rel system table.
    ii) Initiate a transaction.
    iii) For each sequence: a) Obtain the sequence value from the
    publisher by utilizing the pg_sequence_state function. b) Update the
    sequence with the value obtained from the publisher.
    iv) Commit the transaction.
    
    The benefit with the second approach is that if there are large number
    of sequences, the sequence sync can be enhanced to happen in parallel
    and also if there are any locks held on the sequences in the
    publisher, the sequence worker can wait to acquire the lock instead of
    blocking the whole create subscription command which will delay the
    initial copy of the tables too.
    
    3) Refreshing the sequence can be achieved through the existing
    command: ALTER SUBSCRIPTION ... REFRESH PUBLICATION(no syntax change
    here).
    The subscriber identifies stale sequences, meaning sequences present
    in pg_subscription_rel but absent from the publication, and removes
    them from the pg_subscription_rel system table. The subscriber also
    checks for newly added sequences in the publisher and synchronizes
    their values from the publisher using the steps outlined in the
    subscription creation process. It's worth noting that previously
    synchronized sequences won't be synchronized again; the sequence sync
    will occur solely for the newly added sequences.
    
    4) Introducing a new command for refreshing all sequences: ALTER
    SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES.
    The subscriber will remove stale sequences and add newly added
    sequences from the publisher. Following this, it will re-synchronize
    the sequence values for all sequences in the updated list from the
    publisher, following the steps outlined in the subscription creation
    process.
    
    5) Incorporate the pg_sequence_state function to fetch the sequence
    value from the publisher, along with the page LSN. Incorporate
    SetSequence function, which will procure a new relfilenode for the
    sequence and set the new relfilenode with the specified value. This
    will facilitate rollback in case of any failures.
    
    Thoughts?
    
    Regards,
    Vignesh
    
    
    
    
  35. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-12T05:13:31Z

    On Tue, Jun 11, 2024 at 7:36 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 11 Jun 2024 at 12:38, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Tue, Jun 11, 2024 at 12:25 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Mon, 10 Jun 2024 at 14:48, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > > > On Mon, Jun 10, 2024 at 12:43 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > > > >
    > > > > > On Mon, Jun 10, 2024 at 3:14 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > > > > >
    > > > > > > On Fri, Jun 7, 2024 at 7:30 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > > >
    > > > > > > >
    > > > > > > > Are you imagining the behavior for sequences associated with tables
    > > > > > > > differently than the ones defined by the CREATE SEQUENCE .. command? I
    > > > > > > > was thinking that users would associate sequences with publications
    > > > > > > > similar to what we do for tables for both cases. For example, they
    > > > > > > > need to explicitly mention the sequences they want to replicate by
    > > > > > > > commands like CREATE PUBLICATION ... FOR SEQUENCE s1, s2, ...; CREATE
    > > > > > > > PUBLICATION ... FOR ALL SEQUENCES, or CREATE PUBLICATION ... FOR
    > > > > > > > SEQUENCES IN SCHEMA sch1;
    > > > > > > >
    > > > > > > > In this, variants FOR ALL SEQUENCES and SEQUENCES IN SCHEMA sch1
    > > > > > > > should copy both the explicitly defined sequences and sequences
    > > > > > > > defined with the tables. Do you think a different variant for just
    > > > > > > > copying sequences implicitly associated with tables (say for identity
    > > > > > > > columns)?
    > > > > > >
    > > > > > > Oh, I was thinking that your proposal was to copy literally all
    > > > > > > sequences by REPLICA/REFRESH SEQUENCE command.
    > > > > > >
    > > > >
    > > > > I am trying to keep the behavior as close to tables as possible.
    > > > >
    > > > > > > But it seems to make
    > > > > > > sense to explicitly specify the sequences they want to replicate. It
    > > > > > > also means that they can create a publication that has only sequences.
    > > > > > > In this case, even if they create a subscription for that publication,
    > > > > > > we don't launch any apply workers for that subscription. Right?
    > > > > > >
    > > > >
    > > > > Right, good point. I had not thought about this.
    > > > >
    > > > > > > Also, given that the main use case (at least as the first step) is
    > > > > > > version upgrade, do we really need to support SEQUENCES IN SCHEMA and
    > > > > > > even FOR SEQUENCE?
    > > > > >
    > > > >
    > > > > At the very least, we can split the patch to move these variants to a
    > > > > separate patch. Once the main patch is finalized, we can try to
    > > > > evaluate the remaining separately.
    > > >
    > > > I engaged in an offline discussion with Amit about strategizing the
    > > > division of patches to facilitate the review process. We agreed on the
    > > > following split: The first patch will encompass the setting and
    > > > getting of sequence values (core sequence changes). The second patch
    > > > will cover all changes on the publisher side related to "FOR ALL
    > > > SEQUENCES." The third patch will address subscriber side changes aimed
    > > > at synchronizing "FOR ALL SEQUENCES" publications. The fourth patch
    > > > will focus on supporting "FOR SEQUENCE" publication. Lastly, the fifth
    > > > patch will introduce support for  "FOR ALL SEQUENCES IN SCHEMA"
    > > > publication.
    > > >
    > > > I will work on this and share an updated patch for the same soon.
    > >
    > > +1. Sounds like a good plan.
    >
    > Amit and I engaged in an offline discussion regarding the design and
    > contemplated that it could be like below:
    > 1) CREATE PUBLICATION syntax enhancement:
    > CREATE PUBLICATION ... FOR ALL SEQUENCES;
    > The addition of a new column titled "all sequences" in the
    > pg_publication system table will signify whether the publication is
    > designated as all sequences publication or not.
    >
    
    The first approach sounds like we don't create entries for sequences
    in pg_subscription_rel. In this case, how do we know all sequences
    that we need to refresh when executing the REFRESH PUBLICATION
    SEQUENCES command you mentioned below?
    
    > 2)  CREATE SUBSCRIPTION -- no syntax change.
    > Upon creation of a subscription, the following additional steps will
    > be managed by the subscriber:
    > i) The subscriber will retrieve the list of sequences associated with
    > the subscription's publications.
    > ii) For each sequence: a) Retrieve the sequence value from the
    > publisher by invoking the pg_sequence_state function. b) Set the
    > sequence with the value obtained from the publisher. iv) Once the
    > subscription creation is completed, all sequence values will become
    > visible at the subscriber's end.
    
    Sequence values are always copied from the publisher? or does it
    happen only when copy_data = true?
    
    >
    > An alternative design approach could involve retrieving the sequence
    > list from the publisher during subscription creation and inserting the
    > sequences with an "init" state into the pg_subscription_rel system
    > table. These tasks could be executed by a single sequence sync worker,
    > which would:
    > i) Retrieve the list of sequences in the "init" state from the
    > pg_subscription_rel system table.
    > ii) Initiate a transaction.
    > iii) For each sequence: a) Obtain the sequence value from the
    > publisher by utilizing the pg_sequence_state function. b) Update the
    > sequence with the value obtained from the publisher.
    > iv) Commit the transaction.
    >
    > The benefit with the second approach is that if there are large number
    > of sequences, the sequence sync can be enhanced to happen in parallel
    > and also if there are any locks held on the sequences in the
    > publisher, the sequence worker can wait to acquire the lock instead of
    > blocking the whole create subscription command which will delay the
    > initial copy of the tables too.
    
    I prefer to have separate workers to sync sequences. Probably we can
    start with a single worker and extend it to have multiple workers. BTW
    the sequence-sync worker will be taken from
    max_sync_workers_per_subscription pool?
    
    Or yet another idea I came up with is that a tablesync worker will
    synchronize both the table and sequences owned by the table. That is,
    after the tablesync worker caught up with the apply worker, the
    tablesync worker synchronizes sequences associated with the target
    table as well. One benefit would be that at the time of initial table
    sync being completed, the table and its sequence data are consistent.
    As soon as new changes come to the table, it would become inconsistent
    so it might not be helpful much, though. Also, sequences that are not
    owned by any table will still need to be synchronized by someone.
    
    >
    > 3) Refreshing the sequence can be achieved through the existing
    > command: ALTER SUBSCRIPTION ... REFRESH PUBLICATION(no syntax change
    > here).
    > The subscriber identifies stale sequences, meaning sequences present
    > in pg_subscription_rel but absent from the publication, and removes
    > them from the pg_subscription_rel system table. The subscriber also
    > checks for newly added sequences in the publisher and synchronizes
    > their values from the publisher using the steps outlined in the
    > subscription creation process. It's worth noting that previously
    > synchronized sequences won't be synchronized again; the sequence sync
    > will occur solely for the newly added sequences.
    >
    > 4) Introducing a new command for refreshing all sequences: ALTER
    > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES.
    > The subscriber will remove stale sequences and add newly added
    > sequences from the publisher. Following this, it will re-synchronize
    > the sequence values for all sequences in the updated list from the
    > publisher, following the steps outlined in the subscription creation
    > process.
    
    The difference between 3) and 4) is whether or not to re-synchronize
    the previously synchronized sequences. Do we really want to introduce
    a new command for 4)? I felt that we can invent an option say
    copy_all_sequence for the REFRESH PUBLICATION command to cover the 4)
    case.
    
    >
    > 5) Incorporate the pg_sequence_state function to fetch the sequence
    > value from the publisher, along with the page LSN. Incorporate
    > SetSequence function, which will procure a new relfilenode for the
    > sequence and set the new relfilenode with the specified value. This
    > will facilitate rollback in case of any failures.
    
    Does it mean that we create a new relfilenode for every update of the value?
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  36. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2024-06-12T05:21:29Z

    On Tue, Jun 11, 2024 at 4:06 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > Amit and I engaged in an offline discussion regarding the design and
    > contemplated that it could be like below:
    
    If I understand correctly, does this require the sequences to already
    exist on the subscribing node before creating the subscription, or
    will it also copy any non-existing sequences?
    
    > 1) CREATE PUBLICATION syntax enhancement:
    > CREATE PUBLICATION ... FOR ALL SEQUENCES;
    > The addition of a new column titled "all sequences" in the
    > pg_publication system table will signify whether the publication is
    > designated as all sequences publication or not.
    >
    > 2)  CREATE SUBSCRIPTION -- no syntax change.
    > Upon creation of a subscription, the following additional steps will
    > be managed by the subscriber:
    > i) The subscriber will retrieve the list of sequences associated with
    > the subscription's publications.
    > ii) For each sequence: a) Retrieve the sequence value from the
    > publisher by invoking the pg_sequence_state function. b) Set the
    > sequence with the value obtained from the publisher. iv) Once the
    > subscription creation is completed, all sequence values will become
    > visible at the subscriber's end.
    >
    > An alternative design approach could involve retrieving the sequence
    > list from the publisher during subscription creation and inserting the
    > sequences with an "init" state into the pg_subscription_rel system
    > table. These tasks could be executed by a single sequence sync worker,
    > which would:
    > i) Retrieve the list of sequences in the "init" state from the
    > pg_subscription_rel system table.
    > ii) Initiate a transaction.
    > iii) For each sequence: a) Obtain the sequence value from the
    > publisher by utilizing the pg_sequence_state function. b) Update the
    > sequence with the value obtained from the publisher.
    > iv) Commit the transaction.
    >
    > The benefit with the second approach is that if there are large number
    > of sequences, the sequence sync can be enhanced to happen in parallel
    > and also if there are any locks held on the sequences in the
    > publisher, the sequence worker can wait to acquire the lock instead of
    > blocking the whole create subscription command which will delay the
    > initial copy of the tables too.
    
    Yeah w.r.t. this point second approach seems better.
    
    > 3) Refreshing the sequence can be achieved through the existing
    > command: ALTER SUBSCRIPTION ... REFRESH PUBLICATION(no syntax change
    > here).
    > The subscriber identifies stale sequences, meaning sequences present
    > in pg_subscription_rel but absent from the publication, and removes
    > them from the pg_subscription_rel system table. The subscriber also
    > checks for newly added sequences in the publisher and synchronizes
    > their values from the publisher using the steps outlined in the
    > subscription creation process. It's worth noting that previously
    > synchronized sequences won't be synchronized again; the sequence sync
    > will occur solely for the newly added sequences.
    
    > 4) Introducing a new command for refreshing all sequences: ALTER
    > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES.
    > The subscriber will remove stale sequences and add newly added
    > sequences from the publisher. Following this, it will re-synchronize
    > the sequence values for all sequences in the updated list from the
    > publisher, following the steps outlined in the subscription creation
    > process.
    
    Okay, this answers my first question: we will remove the sequences
    that are removed from the publisher and add the new sequences. I don't
    see any problem with this, but doesn't it seem like we are effectively
    doing DDL replication only for sequences without having a
    comprehensive plan for overall DDL replication?
    
    > 5) Incorporate the pg_sequence_state function to fetch the sequence
    > value from the publisher, along with the page LSN. Incorporate
    > SetSequence function, which will procure a new relfilenode for the
    > sequence and set the new relfilenode with the specified value. This
    > will facilitate rollback in case of any failures.
    
    I do not understand this point, you mean whenever we are fetching the
    sequence value from the publisher we need to create a new relfilenode
    on the subscriber?  Why not just update the catalog tuple is
    sufficient?  Or this is for handling the ALTER SEQUENCE case?
    
    -- 
    Regards,
    Dilip Kumar
    EnterpriseDB: http://www.enterprisedb.com
    
    
    
    
  37. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-12T09:59:00Z

    On Wed, Jun 12, 2024 at 10:44 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Tue, Jun 11, 2024 at 7:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > 1) CREATE PUBLICATION syntax enhancement:
    > > CREATE PUBLICATION ... FOR ALL SEQUENCES;
    > > The addition of a new column titled "all sequences" in the
    > > pg_publication system table will signify whether the publication is
    > > designated as all sequences publication or not.
    > >
    >
    > The first approach sounds like we don't create entries for sequences
    > in pg_subscription_rel. In this case, how do we know all sequences
    > that we need to refresh when executing the REFRESH PUBLICATION
    > SEQUENCES command you mentioned below?
    >
    
    As per my understanding, we should be creating entries for sequences
    in pg_subscription_rel similar to tables. The difference would be that
    we won't need all the sync_states (i = initialize, d = data is being
    copied, f = finished table copy, s = synchronized, r = ready) as we
    don't need any synchronization with apply workers.
    
    > > 2)  CREATE SUBSCRIPTION -- no syntax change.
    > > Upon creation of a subscription, the following additional steps will
    > > be managed by the subscriber:
    > > i) The subscriber will retrieve the list of sequences associated with
    > > the subscription's publications.
    > > ii) For each sequence: a) Retrieve the sequence value from the
    > > publisher by invoking the pg_sequence_state function. b) Set the
    > > sequence with the value obtained from the publisher. iv) Once the
    > > subscription creation is completed, all sequence values will become
    > > visible at the subscriber's end.
    >
    > Sequence values are always copied from the publisher? or does it
    > happen only when copy_data = true?
    >
    
    It is better to do it when "copy_data = true" to keep it compatible
    with the table's behavior.
    
    > >
    > > An alternative design approach could involve retrieving the sequence
    > > list from the publisher during subscription creation and inserting the
    > > sequences with an "init" state into the pg_subscription_rel system
    > > table. These tasks could be executed by a single sequence sync worker,
    > > which would:
    > > i) Retrieve the list of sequences in the "init" state from the
    > > pg_subscription_rel system table.
    > > ii) Initiate a transaction.
    > > iii) For each sequence: a) Obtain the sequence value from the
    > > publisher by utilizing the pg_sequence_state function. b) Update the
    > > sequence with the value obtained from the publisher.
    > > iv) Commit the transaction.
    > >
    > > The benefit with the second approach is that if there are large number
    > > of sequences, the sequence sync can be enhanced to happen in parallel
    > > and also if there are any locks held on the sequences in the
    > > publisher, the sequence worker can wait to acquire the lock instead of
    > > blocking the whole create subscription command which will delay the
    > > initial copy of the tables too.
    >
    > I prefer to have separate workers to sync sequences.
    >
    
    +1.
    
    > Probably we can
    > start with a single worker and extend it to have multiple workers.
    
    Yeah, starting with a single worker sounds good for now. Do you think
    we should sync all the sequences in a single transaction or have some
    threshold value above which a different transaction would be required
    or maybe a different sequence sync worker altogether? Now, having
    multiple sequence-sync workers requires some synchronization so that
    only a single worker is allocated for one sequence.
    
    The simplest thing is to use a single sequence sync worker that syncs
    all sequences in one transaction but with a large number of sequences,
    it could be inefficient. OTOH, I am not sure if it would be a problem
    in reality.
    
    >
    > BTW
    > the sequence-sync worker will be taken from
    > max_sync_workers_per_subscription pool?
    >
    
    I think so.
    
    > Or yet another idea I came up with is that a tablesync worker will
    > synchronize both the table and sequences owned by the table. That is,
    > after the tablesync worker caught up with the apply worker, the
    > tablesync worker synchronizes sequences associated with the target
    > table as well. One benefit would be that at the time of initial table
    > sync being completed, the table and its sequence data are consistent.
    > As soon as new changes come to the table, it would become inconsistent
    > so it might not be helpful much, though. Also, sequences that are not
    > owned by any table will still need to be synchronized by someone.
    >
    
    The other thing to consider in this idea is that we somehow need to
    distinguish the sequences owned by the table.
    
    > >
    > > 3) Refreshing the sequence can be achieved through the existing
    > > command: ALTER SUBSCRIPTION ... REFRESH PUBLICATION(no syntax change
    > > here).
    > > The subscriber identifies stale sequences, meaning sequences present
    > > in pg_subscription_rel but absent from the publication, and removes
    > > them from the pg_subscription_rel system table. The subscriber also
    > > checks for newly added sequences in the publisher and synchronizes
    > > their values from the publisher using the steps outlined in the
    > > subscription creation process. It's worth noting that previously
    > > synchronized sequences won't be synchronized again; the sequence sync
    > > will occur solely for the newly added sequences.
    > >
    > > 4) Introducing a new command for refreshing all sequences: ALTER
    > > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES.
    > > The subscriber will remove stale sequences and add newly added
    > > sequences from the publisher. Following this, it will re-synchronize
    > > the sequence values for all sequences in the updated list from the
    > > publisher, following the steps outlined in the subscription creation
    > > process.
    >
    > The difference between 3) and 4) is whether or not to re-synchronize
    > the previously synchronized sequences. Do we really want to introduce
    > a new command for 4)? I felt that we can invent an option say
    > copy_all_sequence for the REFRESH PUBLICATION command to cover the 4)
    > case.
    >
    
    Yeah, that is also an option but it could confuse along with copy_data
    option. Say the user has selected copy_data = false but
    copy_all_sequences = true then the first option indicates to *not*
    copy the data of table and sequences and the second option indicates
    to copy the sequences data which sounds contradictory. The other idea
    is to have an option copy_existing_sequences (which indicates to copy
    existing sequence values) but that also has somewhat the same drawback
    as copy_all_sequences but to a lesser degree.
    
    > >
    > > 5) Incorporate the pg_sequence_state function to fetch the sequence
    > > value from the publisher, along with the page LSN. Incorporate
    > > SetSequence function, which will procure a new relfilenode for the
    > > sequence and set the new relfilenode with the specified value. This
    > > will facilitate rollback in case of any failures.
    >
    > Does it mean that we create a new relfilenode for every update of the value?
    >
    
    We need it for initial sync so that if there is an error both the
    sequence state in pg_subscription_rel and sequence values can be
    rolled back together. However, it is unclear whether we need to create
    a new relfilenode while copying existing sequences (say during ALTER
    SUBSCRIPTION .. REFRESH PUBLICATION SEQUENCES, or whatever command we
    decide)? Probably the answer lies in how we want to implement this
    command. If we want to copy all sequence values during the command
    itself then it is probably okay but if we want to handover this task
    to the sequence-sync worker then we need some state management and a
    new relfilenode so that on error both state and sequence values are
    rolled back.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  38. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-12T10:38:04Z

    On Wed, 12 Jun 2024 at 10:51, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Tue, Jun 11, 2024 at 4:06 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > Amit and I engaged in an offline discussion regarding the design and
    > > contemplated that it could be like below:
    >
    > If I understand correctly, does this require the sequences to already
    > exist on the subscribing node before creating the subscription, or
    > will it also copy any non-existing sequences?
    
    Sequences must exist in the subscriber; we'll synchronize only their
    values. Any sequences that are not present in the subscriber will
    trigger an error.
    
    > > 1) CREATE PUBLICATION syntax enhancement:
    > > CREATE PUBLICATION ... FOR ALL SEQUENCES;
    > > The addition of a new column titled "all sequences" in the
    > > pg_publication system table will signify whether the publication is
    > > designated as all sequences publication or not.
    > >
    > > 2)  CREATE SUBSCRIPTION -- no syntax change.
    > > Upon creation of a subscription, the following additional steps will
    > > be managed by the subscriber:
    > > i) The subscriber will retrieve the list of sequences associated with
    > > the subscription's publications.
    > > ii) For each sequence: a) Retrieve the sequence value from the
    > > publisher by invoking the pg_sequence_state function. b) Set the
    > > sequence with the value obtained from the publisher. iv) Once the
    > > subscription creation is completed, all sequence values will become
    > > visible at the subscriber's end.
    > >
    > > An alternative design approach could involve retrieving the sequence
    > > list from the publisher during subscription creation and inserting the
    > > sequences with an "init" state into the pg_subscription_rel system
    > > table. These tasks could be executed by a single sequence sync worker,
    > > which would:
    > > i) Retrieve the list of sequences in the "init" state from the
    > > pg_subscription_rel system table.
    > > ii) Initiate a transaction.
    > > iii) For each sequence: a) Obtain the sequence value from the
    > > publisher by utilizing the pg_sequence_state function. b) Update the
    > > sequence with the value obtained from the publisher.
    > > iv) Commit the transaction.
    > >
    > > The benefit with the second approach is that if there are large number
    > > of sequences, the sequence sync can be enhanced to happen in parallel
    > > and also if there are any locks held on the sequences in the
    > > publisher, the sequence worker can wait to acquire the lock instead of
    > > blocking the whole create subscription command which will delay the
    > > initial copy of the tables too.
    >
    > Yeah w.r.t. this point second approach seems better.
    
    ok
    
    > > 3) Refreshing the sequence can be achieved through the existing
    > > command: ALTER SUBSCRIPTION ... REFRESH PUBLICATION(no syntax change
    > > here).
    > > The subscriber identifies stale sequences, meaning sequences present
    > > in pg_subscription_rel but absent from the publication, and removes
    > > them from the pg_subscription_rel system table. The subscriber also
    > > checks for newly added sequences in the publisher and synchronizes
    > > their values from the publisher using the steps outlined in the
    > > subscription creation process. It's worth noting that previously
    > > synchronized sequences won't be synchronized again; the sequence sync
    > > will occur solely for the newly added sequences.
    >
    > > 4) Introducing a new command for refreshing all sequences: ALTER
    > > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES.
    > > The subscriber will remove stale sequences and add newly added
    > > sequences from the publisher. Following this, it will re-synchronize
    > > the sequence values for all sequences in the updated list from the
    > > publisher, following the steps outlined in the subscription creation
    > > process.
    >
    > Okay, this answers my first question: we will remove the sequences
    > that are removed from the publisher and add the new sequences. I don't
    > see any problem with this, but doesn't it seem like we are effectively
    > doing DDL replication only for sequences without having a
    > comprehensive plan for overall DDL replication?
    
    What I intended to convey is that we'll eliminate the sequences from
    pg_subscription_rel. We won't facilitate the DDL replication of
    sequences; instead, we anticipate users to create the sequences
    themselves.
    
    > > 5) Incorporate the pg_sequence_state function to fetch the sequence
    > > value from the publisher, along with the page LSN. Incorporate
    > > SetSequence function, which will procure a new relfilenode for the
    > > sequence and set the new relfilenode with the specified value. This
    > > will facilitate rollback in case of any failures.
    >
    > I do not understand this point, you mean whenever we are fetching the
    > sequence value from the publisher we need to create a new relfilenode
    > on the subscriber?  Why not just update the catalog tuple is
    > sufficient?  Or this is for handling the ALTER SEQUENCE case?
    
    Sequences operate distinctively from tables. Alterations to sequences
    reflect instantly in another session, even before committing the
    transaction. To ensure the synchronization of sequence value and state
    updates in pg_subscription_rel, we assign it a new relfilenode. This
    strategy ensures that any potential errors allow for the rollback of
    both the sequence state in pg_subscription_rel and the sequence values
    simultaneously.
    
    Regards,
    Vignesh
    
    
    
    
  39. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2024-06-12T11:38:49Z

    On Wed, Jun 12, 2024 at 4:08 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 12 Jun 2024 at 10:51, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Tue, Jun 11, 2024 at 4:06 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > Amit and I engaged in an offline discussion regarding the design and
    > > > contemplated that it could be like below:
    > >
    > > If I understand correctly, does this require the sequences to already
    > > exist on the subscribing node before creating the subscription, or
    > > will it also copy any non-existing sequences?
    >
    > Sequences must exist in the subscriber; we'll synchronize only their
    > values. Any sequences that are not present in the subscriber will
    > trigger an error.
    
    Okay, that makes sense.
    
    >
    > > > 3) Refreshing the sequence can be achieved through the existing
    > > > command: ALTER SUBSCRIPTION ... REFRESH PUBLICATION(no syntax change
    > > > here).
    > > > The subscriber identifies stale sequences, meaning sequences present
    > > > in pg_subscription_rel but absent from the publication, and removes
    > > > them from the pg_subscription_rel system table. The subscriber also
    > > > checks for newly added sequences in the publisher and synchronizes
    > > > their values from the publisher using the steps outlined in the
    > > > subscription creation process. It's worth noting that previously
    > > > synchronized sequences won't be synchronized again; the sequence sync
    > > > will occur solely for the newly added sequences.
    > >
    > > > 4) Introducing a new command for refreshing all sequences: ALTER
    > > > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES.
    > > > The subscriber will remove stale sequences and add newly added
    > > > sequences from the publisher. Following this, it will re-synchronize
    > > > the sequence values for all sequences in the updated list from the
    > > > publisher, following the steps outlined in the subscription creation
    > > > process.
    > >
    > > Okay, this answers my first question: we will remove the sequences
    > > that are removed from the publisher and add the new sequences. I don't
    > > see any problem with this, but doesn't it seem like we are effectively
    > > doing DDL replication only for sequences without having a
    > > comprehensive plan for overall DDL replication?
    >
    > What I intended to convey is that we'll eliminate the sequences from
    > pg_subscription_rel. We won't facilitate the DDL replication of
    > sequences; instead, we anticipate users to create the sequences
    > themselves.
    
    hmm okay.
    
    > > > 5) Incorporate the pg_sequence_state function to fetch the sequence
    > > > value from the publisher, along with the page LSN. Incorporate
    > > > SetSequence function, which will procure a new relfilenode for the
    > > > sequence and set the new relfilenode with the specified value. This
    > > > will facilitate rollback in case of any failures.
    > >
    > > I do not understand this point, you mean whenever we are fetching the
    > > sequence value from the publisher we need to create a new relfilenode
    > > on the subscriber?  Why not just update the catalog tuple is
    > > sufficient?  Or this is for handling the ALTER SEQUENCE case?
    >
    > Sequences operate distinctively from tables. Alterations to sequences
    > reflect instantly in another session, even before committing the
    > transaction. To ensure the synchronization of sequence value and state
    > updates in pg_subscription_rel, we assign it a new relfilenode. This
    > strategy ensures that any potential errors allow for the rollback of
    > both the sequence state in pg_subscription_rel and the sequence values
    > simultaneously.
    
    So, you're saying that when we synchronize the sequence values on the
    subscriber side, we will create a new relfilenode to allow reverting
    to the old state of the sequence in case of an error or transaction
    rollback? But why would we want to do that? Generally, even if you
    call nextval() on a sequence and then roll back the transaction, the
    sequence value doesn't revert to the old value. So, what specific
    problem on the subscriber side are we trying to avoid by operating on
    a new relfilenode?
    
    -- 
    Regards,
    Dilip Kumar
    EnterpriseDB: http://www.enterprisedb.com
    
    
    
    
  40. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-13T04:40:24Z

    On Wed, 12 Jun 2024 at 17:09, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Wed, Jun 12, 2024 at 4:08 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Wed, 12 Jun 2024 at 10:51, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > >
    > > > On Tue, Jun 11, 2024 at 4:06 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > Amit and I engaged in an offline discussion regarding the design and
    > > > > contemplated that it could be like below:
    > > >
    > > > If I understand correctly, does this require the sequences to already
    > > > exist on the subscribing node before creating the subscription, or
    > > > will it also copy any non-existing sequences?
    > >
    > > Sequences must exist in the subscriber; we'll synchronize only their
    > > values. Any sequences that are not present in the subscriber will
    > > trigger an error.
    >
    > Okay, that makes sense.
    >
    > >
    > > > > 3) Refreshing the sequence can be achieved through the existing
    > > > > command: ALTER SUBSCRIPTION ... REFRESH PUBLICATION(no syntax change
    > > > > here).
    > > > > The subscriber identifies stale sequences, meaning sequences present
    > > > > in pg_subscription_rel but absent from the publication, and removes
    > > > > them from the pg_subscription_rel system table. The subscriber also
    > > > > checks for newly added sequences in the publisher and synchronizes
    > > > > their values from the publisher using the steps outlined in the
    > > > > subscription creation process. It's worth noting that previously
    > > > > synchronized sequences won't be synchronized again; the sequence sync
    > > > > will occur solely for the newly added sequences.
    > > >
    > > > > 4) Introducing a new command for refreshing all sequences: ALTER
    > > > > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES.
    > > > > The subscriber will remove stale sequences and add newly added
    > > > > sequences from the publisher. Following this, it will re-synchronize
    > > > > the sequence values for all sequences in the updated list from the
    > > > > publisher, following the steps outlined in the subscription creation
    > > > > process.
    > > >
    > > > Okay, this answers my first question: we will remove the sequences
    > > > that are removed from the publisher and add the new sequences. I don't
    > > > see any problem with this, but doesn't it seem like we are effectively
    > > > doing DDL replication only for sequences without having a
    > > > comprehensive plan for overall DDL replication?
    > >
    > > What I intended to convey is that we'll eliminate the sequences from
    > > pg_subscription_rel. We won't facilitate the DDL replication of
    > > sequences; instead, we anticipate users to create the sequences
    > > themselves.
    >
    > hmm okay.
    >
    > > > > 5) Incorporate the pg_sequence_state function to fetch the sequence
    > > > > value from the publisher, along with the page LSN. Incorporate
    > > > > SetSequence function, which will procure a new relfilenode for the
    > > > > sequence and set the new relfilenode with the specified value. This
    > > > > will facilitate rollback in case of any failures.
    > > >
    > > > I do not understand this point, you mean whenever we are fetching the
    > > > sequence value from the publisher we need to create a new relfilenode
    > > > on the subscriber?  Why not just update the catalog tuple is
    > > > sufficient?  Or this is for handling the ALTER SEQUENCE case?
    > >
    > > Sequences operate distinctively from tables. Alterations to sequences
    > > reflect instantly in another session, even before committing the
    > > transaction. To ensure the synchronization of sequence value and state
    > > updates in pg_subscription_rel, we assign it a new relfilenode. This
    > > strategy ensures that any potential errors allow for the rollback of
    > > both the sequence state in pg_subscription_rel and the sequence values
    > > simultaneously.
    >
    > So, you're saying that when we synchronize the sequence values on the
    > subscriber side, we will create a new relfilenode to allow reverting
    > to the old state of the sequence in case of an error or transaction
    > rollback? But why would we want to do that? Generally, even if you
    > call nextval() on a sequence and then roll back the transaction, the
    > sequence value doesn't revert to the old value. So, what specific
    > problem on the subscriber side are we trying to avoid by operating on
    > a new relfilenode?
    
    Let's consider a situation where we have two sequences: seq1 with a
    value of 100 and seq2 with a value of 200. Now, let's say seq1 is
    synced and updated to 100, then we attempt to synchronize seq2,
    there's a failure due to the sequence not existing or encountering
    some other issue. In this scenario, we don't want to halt operations
    where seq1 is synchronized, but the sequence state for sequence isn't
    changed to "ready" in pg_subscription_rel.
    Updating the sequence data directly reflects the sequence change
    immediately. However, if we assign a new relfile node for the sequence
    and update the sequence value for the new relfile node, until the
    transaction is committed, other concurrent users will still be
    utilizing the old relfile node for the sequence, and only the old data
    will be visible. Once all sequences are synchronized, and the sequence
    state is updated in pg_subscription_rel, the transaction will either
    be committed or aborted. If committed, users will be able to observe
    the new sequence values because the sequences will be updated with the
    new relfile node containing the updated sequence value.
    
    Regards,
    Vignesh
    
    
    
    
  41. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2024-06-13T04:57:21Z

    On Thu, Jun 13, 2024 at 10:10 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > > So, you're saying that when we synchronize the sequence values on the
    > > subscriber side, we will create a new relfilenode to allow reverting
    > > to the old state of the sequence in case of an error or transaction
    > > rollback? But why would we want to do that? Generally, even if you
    > > call nextval() on a sequence and then roll back the transaction, the
    > > sequence value doesn't revert to the old value. So, what specific
    > > problem on the subscriber side are we trying to avoid by operating on
    > > a new relfilenode?
    >
    > Let's consider a situation where we have two sequences: seq1 with a
    > value of 100 and seq2 with a value of 200. Now, let's say seq1 is
    > synced and updated to 100, then we attempt to synchronize seq2,
    > there's a failure due to the sequence not existing or encountering
    > some other issue. In this scenario, we don't want to halt operations
    > where seq1 is synchronized, but the sequence state for sequence isn't
    > changed to "ready" in pg_subscription_rel.
    
    Thanks for the explanation, but I am still not getting it completely,
    do you mean to say unless all the sequences are not synced any of the
    sequences would not be marked "ready" in pg_subscription_rel? Is that
    necessary? I mean why we can not sync the sequences one by one and
    mark them ready?  Why it is necessary to either have all the sequences
    synced or none of them?
    
    -- 
    Regards,
    Dilip Kumar
    EnterpriseDB: http://www.enterprisedb.com
    
    
    
    
  42. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-13T06:23:34Z

    On Thu, 13 Jun 2024 at 10:27, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Thu, Jun 13, 2024 at 10:10 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > > So, you're saying that when we synchronize the sequence values on the
    > > > subscriber side, we will create a new relfilenode to allow reverting
    > > > to the old state of the sequence in case of an error or transaction
    > > > rollback? But why would we want to do that? Generally, even if you
    > > > call nextval() on a sequence and then roll back the transaction, the
    > > > sequence value doesn't revert to the old value. So, what specific
    > > > problem on the subscriber side are we trying to avoid by operating on
    > > > a new relfilenode?
    > >
    > > Let's consider a situation where we have two sequences: seq1 with a
    > > value of 100 and seq2 with a value of 200. Now, let's say seq1 is
    > > synced and updated to 100, then we attempt to synchronize seq2,
    > > there's a failure due to the sequence not existing or encountering
    > > some other issue. In this scenario, we don't want to halt operations
    > > where seq1 is synchronized, but the sequence state for sequence isn't
    > > changed to "ready" in pg_subscription_rel.
    >
    > Thanks for the explanation, but I am still not getting it completely,
    > do you mean to say unless all the sequences are not synced any of the
    > sequences would not be marked "ready" in pg_subscription_rel? Is that
    > necessary? I mean why we can not sync the sequences one by one and
    > mark them ready?  Why it is necessary to either have all the sequences
    > synced or none of them?
    
    Since updating the sequence is one operation and setting
    pg_subscription_rel is another, I was trying to avoid a situation
    where the sequence is updated but its state is not reflected in
    pg_subscription_rel. It seems you are suggesting that it's acceptable
    for the sequence to be updated even if its state isn't updated in
    pg_subscription_rel, and in such cases, the sequence value does not
    need to be reverted.
    
    Regards,
    Vignesh
    
    
    
    
  43. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2024-06-13T06:42:20Z

    On Thu, Jun 13, 2024 at 11:53 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 13 Jun 2024 at 10:27, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    
    > > Thanks for the explanation, but I am still not getting it completely,
    > > do you mean to say unless all the sequences are not synced any of the
    > > sequences would not be marked "ready" in pg_subscription_rel? Is that
    > > necessary? I mean why we can not sync the sequences one by one and
    > > mark them ready?  Why it is necessary to either have all the sequences
    > > synced or none of them?
    >
    > Since updating the sequence is one operation and setting
    > pg_subscription_rel is another, I was trying to avoid a situation
    > where the sequence is updated but its state is not reflected in
    > pg_subscription_rel. It seems you are suggesting that it's acceptable
    > for the sequence to be updated even if its state isn't updated in
    > pg_subscription_rel, and in such cases, the sequence value does not
    > need to be reverted.
    
    Right, the complexity we're adding to achieve a behavior that may not
    be truly desirable is a concern. For instance, if we mark the status
    as ready but do not sync the sequences, it could lead to issues.
    However, if we have synced some sequences but encounter a failure
    without marking the status as ready, I don't consider it inconsistent
    in any way.  But anyway, now I understand your thinking behind that so
    it's a good idea to leave this design behavior for a later decision.
    Gathering more opinions and insights during later stages will provide
    a clearer perspective on how to proceed with this aspect.  Thanks.
    
    -- 
    Regards,
    Dilip Kumar
    EnterpriseDB: http://www.enterprisedb.com
    
    
    
    
  44. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-13T07:38:41Z

    On Wed, Jun 12, 2024 at 6:59 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Wed, Jun 12, 2024 at 10:44 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Tue, Jun 11, 2024 at 7:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > 1) CREATE PUBLICATION syntax enhancement:
    > > > CREATE PUBLICATION ... FOR ALL SEQUENCES;
    > > > The addition of a new column titled "all sequences" in the
    > > > pg_publication system table will signify whether the publication is
    > > > designated as all sequences publication or not.
    > > >
    > >
    > > The first approach sounds like we don't create entries for sequences
    > > in pg_subscription_rel. In this case, how do we know all sequences
    > > that we need to refresh when executing the REFRESH PUBLICATION
    > > SEQUENCES command you mentioned below?
    > >
    >
    > As per my understanding, we should be creating entries for sequences
    > in pg_subscription_rel similar to tables. The difference would be that
    > we won't need all the sync_states (i = initialize, d = data is being
    > copied, f = finished table copy, s = synchronized, r = ready) as we
    > don't need any synchronization with apply workers.
    
    Agreed.
    
    >
    > > > 2)  CREATE SUBSCRIPTION -- no syntax change.
    > > > Upon creation of a subscription, the following additional steps will
    > > > be managed by the subscriber:
    > > > i) The subscriber will retrieve the list of sequences associated with
    > > > the subscription's publications.
    > > > ii) For each sequence: a) Retrieve the sequence value from the
    > > > publisher by invoking the pg_sequence_state function. b) Set the
    > > > sequence with the value obtained from the publisher. iv) Once the
    > > > subscription creation is completed, all sequence values will become
    > > > visible at the subscriber's end.
    > >
    > > Sequence values are always copied from the publisher? or does it
    > > happen only when copy_data = true?
    > >
    >
    > It is better to do it when "copy_data = true" to keep it compatible
    > with the table's behavior.
    
    +1
    
    >
    > > Probably we can
    > > start with a single worker and extend it to have multiple workers.
    >
    > Yeah, starting with a single worker sounds good for now. Do you think
    > we should sync all the sequences in a single transaction or have some
    > threshold value above which a different transaction would be required
    > or maybe a different sequence sync worker altogether? Now, having
    > multiple sequence-sync workers requires some synchronization so that
    > only a single worker is allocated for one sequence.
    >
    > The simplest thing is to use a single sequence sync worker that syncs
    > all sequences in one transaction but with a large number of sequences,
    > it could be inefficient. OTOH, I am not sure if it would be a problem
    > in reality.
    
    I think that we can start with using a single worker and one
    transaction, and measure the performance with a large number of
    sequences.
    
    > > Or yet another idea I came up with is that a tablesync worker will
    > > synchronize both the table and sequences owned by the table. That is,
    > > after the tablesync worker caught up with the apply worker, the
    > > tablesync worker synchronizes sequences associated with the target
    > > table as well. One benefit would be that at the time of initial table
    > > sync being completed, the table and its sequence data are consistent.
    
    Correction; it's not guaranteed that the sequence data and table data
    are consistent even in this case since the tablesync worker could get
    on-disk sequence data that might have already been updated.
    
    > > As soon as new changes come to the table, it would become inconsistent
    > > so it might not be helpful much, though. Also, sequences that are not
    > > owned by any table will still need to be synchronized by someone.
    > >
    >
    > The other thing to consider in this idea is that we somehow need to
    > distinguish the sequences owned by the table.
    
    I think we can check pg_depend. The owned sequences reference to the table.
    
    >
    > > >
    > > > 3) Refreshing the sequence can be achieved through the existing
    > > > command: ALTER SUBSCRIPTION ... REFRESH PUBLICATION(no syntax change
    > > > here).
    > > > The subscriber identifies stale sequences, meaning sequences present
    > > > in pg_subscription_rel but absent from the publication, and removes
    > > > them from the pg_subscription_rel system table. The subscriber also
    > > > checks for newly added sequences in the publisher and synchronizes
    > > > their values from the publisher using the steps outlined in the
    > > > subscription creation process. It's worth noting that previously
    > > > synchronized sequences won't be synchronized again; the sequence sync
    > > > will occur solely for the newly added sequences.
    > > >
    > > > 4) Introducing a new command for refreshing all sequences: ALTER
    > > > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES.
    > > > The subscriber will remove stale sequences and add newly added
    > > > sequences from the publisher. Following this, it will re-synchronize
    > > > the sequence values for all sequences in the updated list from the
    > > > publisher, following the steps outlined in the subscription creation
    > > > process.
    > >
    > > The difference between 3) and 4) is whether or not to re-synchronize
    > > the previously synchronized sequences. Do we really want to introduce
    > > a new command for 4)? I felt that we can invent an option say
    > > copy_all_sequence for the REFRESH PUBLICATION command to cover the 4)
    > > case.
    > >
    >
    > Yeah, that is also an option but it could confuse along with copy_data
    > option. Say the user has selected copy_data = false but
    > copy_all_sequences = true then the first option indicates to *not*
    > copy the data of table and sequences and the second option indicates
    > to copy the sequences data which sounds contradictory. The other idea
    > is to have an option copy_existing_sequences (which indicates to copy
    > existing sequence values) but that also has somewhat the same drawback
    > as copy_all_sequences but to a lesser degree.
    
    Good point. And I understood that the REFRESH PUBLICATION SEQUENCES
    command would be helpful when users want to synchronize sequences
    between two nodes before upgrading.
    
    >
    > > >
    > > > 5) Incorporate the pg_sequence_state function to fetch the sequence
    > > > value from the publisher, along with the page LSN. Incorporate
    > > > SetSequence function, which will procure a new relfilenode for the
    > > > sequence and set the new relfilenode with the specified value. This
    > > > will facilitate rollback in case of any failures.
    > >
    > > Does it mean that we create a new relfilenode for every update of the value?
    > >
    >
    > We need it for initial sync so that if there is an error both the
    > sequence state in pg_subscription_rel and sequence values can be
    > rolled back together.
    
    Agreed.
    
    > However, it is unclear whether we need to create
    > a new relfilenode while copying existing sequences (say during ALTER
    > SUBSCRIPTION .. REFRESH PUBLICATION SEQUENCES, or whatever command we
    > decide)? Probably the answer lies in how we want to implement this
    > command. If we want to copy all sequence values during the command
    > itself then it is probably okay but if we want to handover this task
    > to the sequence-sync worker then we need some state management and a
    > new relfilenode so that on error both state and sequence values are
    > rolled back.
    
    What state transition of pg_subscription_rel entries for sequences do
    we need while copying sequences values? For example, we insert an
    entry with 'init' state at CREATE SUBSCRIPTION and then the
    sequence-sync worker updates to 'ready' and copies the sequence data.
    And at REFRESH PUBLICATION SEQUENCES, we update the state back to
    'init' again so that the sequence-sync worker can process it? Given
    REFRESH PUBLICATION SEQUENCES won't be executed very frequently, it
    might be acceptable to transactionally update sequence values.
    
    
    Regards,
    
    --
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  45. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-13T10:06:05Z

    On Thu, Jun 13, 2024 at 1:09 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Wed, Jun 12, 2024 at 6:59 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > >
    > > Yeah, starting with a single worker sounds good for now. Do you think
    > > we should sync all the sequences in a single transaction or have some
    > > threshold value above which a different transaction would be required
    > > or maybe a different sequence sync worker altogether? Now, having
    > > multiple sequence-sync workers requires some synchronization so that
    > > only a single worker is allocated for one sequence.
    > >
    > > The simplest thing is to use a single sequence sync worker that syncs
    > > all sequences in one transaction but with a large number of sequences,
    > > it could be inefficient. OTOH, I am not sure if it would be a problem
    > > in reality.
    >
    > I think that we can start with using a single worker and one
    > transaction, and measure the performance with a large number of
    > sequences.
    >
    
    Fair enough. However, this raises the question Dilip and Vignesh are
    discussing whether we need a new relfilenode for sequence update even
    during initial sync? As per my understanding, the idea is that similar
    to tables, the CREATE SUBSCRIPTION command (with copy_data = true)
    will create the new sequence entries in pg_subscription_rel with the
    state as 'i'. Then the sequence-sync worker would start a transaction
    and one-by-one copy the latest sequence values for each sequence (that
    has state as 'i' in pg_subscription_rel) and mark its state as ready
    'r' and commit the transaction. Now if there is an error during this
    operation it will restart the entire operation. The idea of creating a
    new relfilenode is to handle the error so that if there is a rollback,
    the sequence state will be rolled back to 'i' and the sequence value
    will also be rolled back. The other option could be that we update the
    sequence value without a new relfilenode and if the transaction rolled
    back then only the sequence's state will be rolled back to 'i'. This
    would work with a minor inconsistency that sequence values will be
    up-to-date even when the sequence state is 'i' in pg_subscription_rel.
    I am not sure if that matters because anyway, they can quickly be
    out-of-sync with the publisher again.
    
    Now, say we don't want to maintain the state of sequences for initial
    sync at all then after the error how will we detect if there are any
    pending sequences to be synced? One possibility is that we maintain a
    subscription level flag 'subsequencesync' in 'pg_subscription' to
    indicate whether sequences need sync. This flag would indicate whether
    to sync all the sequences in pg_susbcription_rel. This would mean that
    if there is an error while syncing the sequences we will resync all
    the sequences again. This could be acceptable considering the chances
    of error during sequence sync are low. The benefit is that both the
    REFRESH PUBLICATION SEQUENCES and CREATE SUBSCRIPTION can use the same
    idea and sync all sequences without needing a new relfilenode. Users
    can always refer 'subsequencesync' flag in 'pg_subscription' to see if
    all the sequences are synced after executing the command.
    
    > > > Or yet another idea I came up with is that a tablesync worker will
    > > > synchronize both the table and sequences owned by the table. That is,
    > > > after the tablesync worker caught up with the apply worker, the
    > > > tablesync worker synchronizes sequences associated with the target
    > > > table as well. One benefit would be that at the time of initial table
    > > > sync being completed, the table and its sequence data are consistent.
    >
    > Correction; it's not guaranteed that the sequence data and table data
    > are consistent even in this case since the tablesync worker could get
    > on-disk sequence data that might have already been updated.
    >
    
    The benefit of this approach is not clear to me. Our aim is to sync
    all sequences before the upgrade, so not sure if this helps because
    anyway both table values and corresponding sequences can again be
    out-of-sync very quickly.
    
    > >
    > > > >
    > > > > 3) Refreshing the sequence can be achieved through the existing
    > > > > command: ALTER SUBSCRIPTION ... REFRESH PUBLICATION(no syntax change
    > > > > here).
    > > > > The subscriber identifies stale sequences, meaning sequences present
    > > > > in pg_subscription_rel but absent from the publication, and removes
    > > > > them from the pg_subscription_rel system table. The subscriber also
    > > > > checks for newly added sequences in the publisher and synchronizes
    > > > > their values from the publisher using the steps outlined in the
    > > > > subscription creation process. It's worth noting that previously
    > > > > synchronized sequences won't be synchronized again; the sequence sync
    > > > > will occur solely for the newly added sequences.
    > > > >
    > > > > 4) Introducing a new command for refreshing all sequences: ALTER
    > > > > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES.
    > > > > The subscriber will remove stale sequences and add newly added
    > > > > sequences from the publisher. Following this, it will re-synchronize
    > > > > the sequence values for all sequences in the updated list from the
    > > > > publisher, following the steps outlined in the subscription creation
    > > > > process.
    > > >
    > > > The difference between 3) and 4) is whether or not to re-synchronize
    > > > the previously synchronized sequences. Do we really want to introduce
    > > > a new command for 4)? I felt that we can invent an option say
    > > > copy_all_sequence for the REFRESH PUBLICATION command to cover the 4)
    > > > case.
    > > >
    > >
    > > Yeah, that is also an option but it could confuse along with copy_data
    > > option. Say the user has selected copy_data = false but
    > > copy_all_sequences = true then the first option indicates to *not*
    > > copy the data of table and sequences and the second option indicates
    > > to copy the sequences data which sounds contradictory. The other idea
    > > is to have an option copy_existing_sequences (which indicates to copy
    > > existing sequence values) but that also has somewhat the same drawback
    > > as copy_all_sequences but to a lesser degree.
    >
    > Good point. And I understood that the REFRESH PUBLICATION SEQUENCES
    > command would be helpful when users want to synchronize sequences
    > between two nodes before upgrading.
    >
    
    Right.
    
    > >
    > > > >
    > > > > 5) Incorporate the pg_sequence_state function to fetch the sequence
    > > > > value from the publisher, along with the page LSN. Incorporate
    > > > > SetSequence function, which will procure a new relfilenode for the
    > > > > sequence and set the new relfilenode with the specified value. This
    > > > > will facilitate rollback in case of any failures.
    > > >
    > > > Does it mean that we create a new relfilenode for every update of the value?
    > > >
    > >
    > > We need it for initial sync so that if there is an error both the
    > > sequence state in pg_subscription_rel and sequence values can be
    > > rolled back together.
    >
    > Agreed.
    >
    > > However, it is unclear whether we need to create
    > > a new relfilenode while copying existing sequences (say during ALTER
    > > SUBSCRIPTION .. REFRESH PUBLICATION SEQUENCES, or whatever command we
    > > decide)? Probably the answer lies in how we want to implement this
    > > command. If we want to copy all sequence values during the command
    > > itself then it is probably okay but if we want to handover this task
    > > to the sequence-sync worker then we need some state management and a
    > > new relfilenode so that on error both state and sequence values are
    > > rolled back.
    >
    > What state transition of pg_subscription_rel entries for sequences do
    > we need while copying sequences values? For example, we insert an
    > entry with 'init' state at CREATE SUBSCRIPTION and then the
    > sequence-sync worker updates to 'ready' and copies the sequence data.
    > And at REFRESH PUBLICATION SEQUENCES, we update the state back to
    > 'init' again so that the sequence-sync worker can process it? Given
    > REFRESH PUBLICATION SEQUENCES won't be executed very frequently, it
    > might be acceptable to transactionally update sequence values.
    >
    
    Do you mean that sync the sequences during the REFRESH PUBLICATION
    SEQUENCES command itself? If so, there is an argument that we can do
    the same during CREATE SUBSCRIPTION. It would be beneficial to keep
    the method to sync the sequences same for both the CREATE and REFRESH
    commands. I have speculated on one idea above and would be happy to
    see your thoughts.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  46. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-13T12:44:05Z

    On Thu, Jun 13, 2024 at 7:06 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Jun 13, 2024 at 1:09 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Wed, Jun 12, 2024 at 6:59 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > >
    > > > Yeah, starting with a single worker sounds good for now. Do you think
    > > > we should sync all the sequences in a single transaction or have some
    > > > threshold value above which a different transaction would be required
    > > > or maybe a different sequence sync worker altogether? Now, having
    > > > multiple sequence-sync workers requires some synchronization so that
    > > > only a single worker is allocated for one sequence.
    > > >
    > > > The simplest thing is to use a single sequence sync worker that syncs
    > > > all sequences in one transaction but with a large number of sequences,
    > > > it could be inefficient. OTOH, I am not sure if it would be a problem
    > > > in reality.
    > >
    > > I think that we can start with using a single worker and one
    > > transaction, and measure the performance with a large number of
    > > sequences.
    > >
    >
    > Fair enough. However, this raises the question Dilip and Vignesh are
    > discussing whether we need a new relfilenode for sequence update even
    > during initial sync? As per my understanding, the idea is that similar
    > to tables, the CREATE SUBSCRIPTION command (with copy_data = true)
    > will create the new sequence entries in pg_subscription_rel with the
    > state as 'i'. Then the sequence-sync worker would start a transaction
    > and one-by-one copy the latest sequence values for each sequence (that
    > has state as 'i' in pg_subscription_rel) and mark its state as ready
    > 'r' and commit the transaction. Now if there is an error during this
    > operation it will restart the entire operation. The idea of creating a
    > new relfilenode is to handle the error so that if there is a rollback,
    > the sequence state will be rolled back to 'i' and the sequence value
    > will also be rolled back. The other option could be that we update the
    > sequence value without a new relfilenode and if the transaction rolled
    > back then only the sequence's state will be rolled back to 'i'. This
    > would work with a minor inconsistency that sequence values will be
    > up-to-date even when the sequence state is 'i' in pg_subscription_rel.
    > I am not sure if that matters because anyway, they can quickly be
    > out-of-sync with the publisher again.
    
    I think it would be fine in many cases even if the sequence value is
    up-to-date even when the sequence state is 'i' in pg_subscription_rel.
    But the case we would like to avoid is where suppose the sequence-sync
    worker does both synchronizing sequence values and updating the
    sequence states for all sequences in one transaction, and if there is
    an error we end up retrying the synchronization for all sequences.
    
    >
    > Now, say we don't want to maintain the state of sequences for initial
    > sync at all then after the error how will we detect if there are any
    > pending sequences to be synced? One possibility is that we maintain a
    > subscription level flag 'subsequencesync' in 'pg_subscription' to
    > indicate whether sequences need sync. This flag would indicate whether
    > to sync all the sequences in pg_susbcription_rel. This would mean that
    > if there is an error while syncing the sequences we will resync all
    > the sequences again. This could be acceptable considering the chances
    > of error during sequence sync are low. The benefit is that both the
    > REFRESH PUBLICATION SEQUENCES and CREATE SUBSCRIPTION can use the same
    > idea and sync all sequences without needing a new relfilenode. Users
    > can always refer 'subsequencesync' flag in 'pg_subscription' to see if
    > all the sequences are synced after executing the command.
    
    I think that REFRESH PUBLICATION {SEQUENCES} can be executed even
    while the sequence-sync worker is synchronizing sequences. In this
    case, the worker might not see new sequences added by the concurrent
    REFRESH PUBLICATION {SEQUENCES} command since it's already running.
    The worker could end up marking the subsequencesync as completed while
    not synchronizing these new sequences.
    
    >
    > > > > Or yet another idea I came up with is that a tablesync worker will
    > > > > synchronize both the table and sequences owned by the table. That is,
    > > > > after the tablesync worker caught up with the apply worker, the
    > > > > tablesync worker synchronizes sequences associated with the target
    > > > > table as well. One benefit would be that at the time of initial table
    > > > > sync being completed, the table and its sequence data are consistent.
    > >
    > > Correction; it's not guaranteed that the sequence data and table data
    > > are consistent even in this case since the tablesync worker could get
    > > on-disk sequence data that might have already been updated.
    > >
    >
    > The benefit of this approach is not clear to me. Our aim is to sync
    > all sequences before the upgrade, so not sure if this helps because
    > anyway both table values and corresponding sequences can again be
    > out-of-sync very quickly.
    
    Right.
    
    Given that our aim is to sync all sequences before the upgrade, do we
    need to synchronize sequences even at CREATE SUBSCRIPTION time? In
    cases where there are a large number of sequences, synchronizing
    sequences in addition to tables could be overhead and make less sense,
    because sequences can again be out-of-sync quickly and typically
    CREATE SUBSCRIPTION is not created just before the upgrade.
    
    >
    > > >
    > > > > >
    > > > > > 5) Incorporate the pg_sequence_state function to fetch the sequence
    > > > > > value from the publisher, along with the page LSN. Incorporate
    > > > > > SetSequence function, which will procure a new relfilenode for the
    > > > > > sequence and set the new relfilenode with the specified value. This
    > > > > > will facilitate rollback in case of any failures.
    > > > >
    > > > > Does it mean that we create a new relfilenode for every update of the value?
    > > > >
    > > >
    > > > We need it for initial sync so that if there is an error both the
    > > > sequence state in pg_subscription_rel and sequence values can be
    > > > rolled back together.
    > >
    > > Agreed.
    > >
    > > > However, it is unclear whether we need to create
    > > > a new relfilenode while copying existing sequences (say during ALTER
    > > > SUBSCRIPTION .. REFRESH PUBLICATION SEQUENCES, or whatever command we
    > > > decide)? Probably the answer lies in how we want to implement this
    > > > command. If we want to copy all sequence values during the command
    > > > itself then it is probably okay but if we want to handover this task
    > > > to the sequence-sync worker then we need some state management and a
    > > > new relfilenode so that on error both state and sequence values are
    > > > rolled back.
    > >
    > > What state transition of pg_subscription_rel entries for sequences do
    > > we need while copying sequences values? For example, we insert an
    > > entry with 'init' state at CREATE SUBSCRIPTION and then the
    > > sequence-sync worker updates to 'ready' and copies the sequence data.
    > > And at REFRESH PUBLICATION SEQUENCES, we update the state back to
    > > 'init' again so that the sequence-sync worker can process it? Given
    > > REFRESH PUBLICATION SEQUENCES won't be executed very frequently, it
    > > might be acceptable to transactionally update sequence values.
    > >
    >
    > Do you mean that sync the sequences during the REFRESH PUBLICATION
    > SEQUENCES command itself? If so, there is an argument that we can do
    > the same during CREATE SUBSCRIPTION. It would be beneficial to keep
    > the method to sync the sequences same for both the CREATE and REFRESH
    > commands. I have speculated on one idea above and would be happy to
    > see your thoughts.
    
    I meant that the REFRESH PUBLICATION SEQUENCES command updates all
    sequence states in pg_subscription_rel to 'init' state, and the
    sequence-sync worker can do the synchronization work. We use the same
    method for both the CREATE SUBSCRIPTION and REFRESH PUBLICATION
    {SEQUENCES} commands.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  47. Re: Logical Replication of sequences

    Michael Paquier <michael@paquier.xyz> — 2024-06-13T23:45:35Z

    On Thu, Jun 13, 2024 at 03:36:05PM +0530, Amit Kapila wrote:
    > Fair enough. However, this raises the question Dilip and Vignesh are
    > discussing whether we need a new relfilenode for sequence update even
    > during initial sync? As per my understanding, the idea is that similar
    > to tables, the CREATE SUBSCRIPTION command (with copy_data = true)
    > will create the new sequence entries in pg_subscription_rel with the
    > state as 'i'. Then the sequence-sync worker would start a transaction
    > and one-by-one copy the latest sequence values for each sequence (that
    > has state as 'i' in pg_subscription_rel) and mark its state as ready
    > 'r' and commit the transaction. Now if there is an error during this
    > operation it will restart the entire operation.
    
    Hmm.  You mean to use only one transaction for all the sequences?
    I've heard about deployments with a lot of them.  Could it be a
    problem to process them in batches, as well?  If you maintain a state
    for each one of them in pg_subscription_rel, it does not strike me as
    an issue, while being more flexible than an all-or-nothing.
    
    > The idea of creating a
    > new relfilenode is to handle the error so that if there is a rollback,
    > the sequence state will be rolled back to 'i' and the sequence value
    > will also be rolled back. The other option could be that we update the
    > sequence value without a new relfilenode and if the transaction rolled
    > back then only the sequence's state will be rolled back to 'i'. This
    > would work with a minor inconsistency that sequence values will be
    > up-to-date even when the sequence state is 'i' in pg_subscription_rel.
    > I am not sure if that matters because anyway, they can quickly be
    > out-of-sync with the publisher again.
    
    Seeing a mention to relfilenodes specifically for sequences freaks me
    out a bit, because there's some work I have been doing in this area
    and sequences may not have a need for a physical relfilenode at all.
    But I guess that you refer to the fact that like tables, relfilenodes
    would only be created as required because anything you'd do in the
    apply worker path would just call some of the routines of sequence.h,
    right?
    
    > Now, say we don't want to maintain the state of sequences for initial
    > sync at all then after the error how will we detect if there are any
    > pending sequences to be synced? One possibility is that we maintain a
    > subscription level flag 'subsequencesync' in 'pg_subscription' to
    > indicate whether sequences need sync. This flag would indicate whether
    > to sync all the sequences in pg_susbcription_rel. This would mean that
    > if there is an error while syncing the sequences we will resync all
    > the sequences again. This could be acceptable considering the chances
    > of error during sequence sync are low.
    
    There could be multiple subscriptions to a single database that point
    to the same set of sequences.  Is there any conflict issue to worry
    about here?
    
    > The benefit is that both the
    > REFRESH PUBLICATION SEQUENCES and CREATE SUBSCRIPTION can use the same
    > idea and sync all sequences without needing a new relfilenode. Users
    > can always refer 'subsequencesync' flag in 'pg_subscription' to see if
    > all the sequences are synced after executing the command.
    
    That would be cheaper, indeed.  Isn't a boolean too limiting?
    Isn't that something you'd want to track with a LSN as "the point in
    WAL where all the sequences have been synced"? 
    
    The approach of doing all the sync work from the subscriber, while
    having a command that can be kicked from the subscriber side is a good
    user experience.
    --
    Michael
    
  48. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-14T07:03:48Z

    On Thu, Jun 13, 2024 at 6:14 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Thu, Jun 13, 2024 at 7:06 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Thu, Jun 13, 2024 at 1:09 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > >
    > > > On Wed, Jun 12, 2024 at 6:59 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > > >
    > > > > Yeah, starting with a single worker sounds good for now. Do you think
    > > > > we should sync all the sequences in a single transaction or have some
    > > > > threshold value above which a different transaction would be required
    > > > > or maybe a different sequence sync worker altogether? Now, having
    > > > > multiple sequence-sync workers requires some synchronization so that
    > > > > only a single worker is allocated for one sequence.
    > > > >
    > > > > The simplest thing is to use a single sequence sync worker that syncs
    > > > > all sequences in one transaction but with a large number of sequences,
    > > > > it could be inefficient. OTOH, I am not sure if it would be a problem
    > > > > in reality.
    > > >
    > > > I think that we can start with using a single worker and one
    > > > transaction, and measure the performance with a large number of
    > > > sequences.
    > > >
    > >
    > > Fair enough. However, this raises the question Dilip and Vignesh are
    > > discussing whether we need a new relfilenode for sequence update even
    > > during initial sync? As per my understanding, the idea is that similar
    > > to tables, the CREATE SUBSCRIPTION command (with copy_data = true)
    > > will create the new sequence entries in pg_subscription_rel with the
    > > state as 'i'. Then the sequence-sync worker would start a transaction
    > > and one-by-one copy the latest sequence values for each sequence (that
    > > has state as 'i' in pg_subscription_rel) and mark its state as ready
    > > 'r' and commit the transaction. Now if there is an error during this
    > > operation it will restart the entire operation. The idea of creating a
    > > new relfilenode is to handle the error so that if there is a rollback,
    > > the sequence state will be rolled back to 'i' and the sequence value
    > > will also be rolled back. The other option could be that we update the
    > > sequence value without a new relfilenode and if the transaction rolled
    > > back then only the sequence's state will be rolled back to 'i'. This
    > > would work with a minor inconsistency that sequence values will be
    > > up-to-date even when the sequence state is 'i' in pg_subscription_rel.
    > > I am not sure if that matters because anyway, they can quickly be
    > > out-of-sync with the publisher again.
    >
    > I think it would be fine in many cases even if the sequence value is
    > up-to-date even when the sequence state is 'i' in pg_subscription_rel.
    > But the case we would like to avoid is where suppose the sequence-sync
    > worker does both synchronizing sequence values and updating the
    > sequence states for all sequences in one transaction, and if there is
    > an error we end up retrying the synchronization for all sequences.
    >
    
    The one idea to avoid this is to update sequences in chunks (say 100
    or some threshold number of sequences in one transaction). Then we
    would only redo the sync for the last and pending set of sequences.
    
    > >
    > > Now, say we don't want to maintain the state of sequences for initial
    > > sync at all then after the error how will we detect if there are any
    > > pending sequences to be synced? One possibility is that we maintain a
    > > subscription level flag 'subsequencesync' in 'pg_subscription' to
    > > indicate whether sequences need sync. This flag would indicate whether
    > > to sync all the sequences in pg_susbcription_rel. This would mean that
    > > if there is an error while syncing the sequences we will resync all
    > > the sequences again. This could be acceptable considering the chances
    > > of error during sequence sync are low. The benefit is that both the
    > > REFRESH PUBLICATION SEQUENCES and CREATE SUBSCRIPTION can use the same
    > > idea and sync all sequences without needing a new relfilenode. Users
    > > can always refer 'subsequencesync' flag in 'pg_subscription' to see if
    > > all the sequences are synced after executing the command.
    >
    > I think that REFRESH PUBLICATION {SEQUENCES} can be executed even
    > while the sequence-sync worker is synchronizing sequences. In this
    > case, the worker might not see new sequences added by the concurrent
    > REFRESH PUBLICATION {SEQUENCES} command since it's already running.
    > The worker could end up marking the subsequencesync as completed while
    > not synchronizing these new sequences.
    >
    
    This is possible but we could avoid REFRESH PUBLICATION {SEQUENCES} by
    not allowing to change the subsequencestate during the time
    sequence-worker is syncing the sequences. This could be restrictive
    but there doesn't seem to be cases where user would like to
    immediately refresh sequences after creating the subscription.
    
    > >
    > > > > > Or yet another idea I came up with is that a tablesync worker will
    > > > > > synchronize both the table and sequences owned by the table. That is,
    > > > > > after the tablesync worker caught up with the apply worker, the
    > > > > > tablesync worker synchronizes sequences associated with the target
    > > > > > table as well. One benefit would be that at the time of initial table
    > > > > > sync being completed, the table and its sequence data are consistent.
    > > >
    > > > Correction; it's not guaranteed that the sequence data and table data
    > > > are consistent even in this case since the tablesync worker could get
    > > > on-disk sequence data that might have already been updated.
    > > >
    > >
    > > The benefit of this approach is not clear to me. Our aim is to sync
    > > all sequences before the upgrade, so not sure if this helps because
    > > anyway both table values and corresponding sequences can again be
    > > out-of-sync very quickly.
    >
    > Right.
    >
    > Given that our aim is to sync all sequences before the upgrade, do we
    > need to synchronize sequences even at CREATE SUBSCRIPTION time? In
    > cases where there are a large number of sequences, synchronizing
    > sequences in addition to tables could be overhead and make less sense,
    > because sequences can again be out-of-sync quickly and typically
    > CREATE SUBSCRIPTION is not created just before the upgrade.
    >
    
    I think for the upgrade one should be creating a subscription just
    before the upgrade. Isn't something similar is done even in the
    upgrade steps you shared once [1]? Typically users should get all the
    data from the publisher before the upgrade of the publisher via
    creating a subscription. Also, it would be better to keep the
    implementation of sequences close to tables wherever possible. Having
    said that, I understand your point as well and if you strongly feel
    that we don't need to sync sequences at the time of CREATE
    SUBSCRIPTION and others also don't see any problem with it then we can
    consider that as well.
    
    > > >
    > >
    > > Do you mean that sync the sequences during the REFRESH PUBLICATION
    > > SEQUENCES command itself? If so, there is an argument that we can do
    > > the same during CREATE SUBSCRIPTION. It would be beneficial to keep
    > > the method to sync the sequences same for both the CREATE and REFRESH
    > > commands. I have speculated on one idea above and would be happy to
    > > see your thoughts.
    >
    > I meant that the REFRESH PUBLICATION SEQUENCES command updates all
    > sequence states in pg_subscription_rel to 'init' state, and the
    > sequence-sync worker can do the synchronization work. We use the same
    > method for both the CREATE SUBSCRIPTION and REFRESH PUBLICATION
    > {SEQUENCES} commands.
    >
    
    Marking the state as 'init' when we would have already synced the
    sequences sounds a bit odd but otherwise, this could also work if we
    accept that even if the sequences are synced and value could remain in
    'init' state (on rollbacks).
    
    
    [1] - https://knock.app/blog/zero-downtime-postgres-upgrades
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  49. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-14T10:00:17Z

    On Fri, Jun 14, 2024 at 5:16 AM Michael Paquier <michael@paquier.xyz> wrote:
    >
    > On Thu, Jun 13, 2024 at 03:36:05PM +0530, Amit Kapila wrote:
    > > Fair enough. However, this raises the question Dilip and Vignesh are
    > > discussing whether we need a new relfilenode for sequence update even
    > > during initial sync? As per my understanding, the idea is that similar
    > > to tables, the CREATE SUBSCRIPTION command (with copy_data = true)
    > > will create the new sequence entries in pg_subscription_rel with the
    > > state as 'i'. Then the sequence-sync worker would start a transaction
    > > and one-by-one copy the latest sequence values for each sequence (that
    > > has state as 'i' in pg_subscription_rel) and mark its state as ready
    > > 'r' and commit the transaction. Now if there is an error during this
    > > operation it will restart the entire operation.
    >
    > Hmm.  You mean to use only one transaction for all the sequences?
    > I've heard about deployments with a lot of them.  Could it be a
    > problem to process them in batches, as well?
    
    I don't think so. We can even sync one sequence per transaction but
    then it would be resource and time consuming without much gain. As
    mentioned in a previous email, we might want to sync 100 or some other
    threshold number of sequences per transaction. The other possibility
    is to make a subscription-level option for this batch size but I don't
    see much advantage in doing so as it won't be convenient for users to
    set it. I feel we should pick some threshold number that is neither
    too low nor too high and if we later see any problem with it, we can
    make it a configurable knob.
    
    >
    > > The idea of creating a
    > > new relfilenode is to handle the error so that if there is a rollback,
    > > the sequence state will be rolled back to 'i' and the sequence value
    > > will also be rolled back. The other option could be that we update the
    > > sequence value without a new relfilenode and if the transaction rolled
    > > back then only the sequence's state will be rolled back to 'i'. This
    > > would work with a minor inconsistency that sequence values will be
    > > up-to-date even when the sequence state is 'i' in pg_subscription_rel.
    > > I am not sure if that matters because anyway, they can quickly be
    > > out-of-sync with the publisher again.
    >
    > Seeing a mention to relfilenodes specifically for sequences freaks me
    > out a bit, because there's some work I have been doing in this area
    > and sequences may not have a need for a physical relfilenode at all.
    > But I guess that you refer to the fact that like tables, relfilenodes
    > would only be created as required because anything you'd do in the
    > apply worker path would just call some of the routines of sequence.h,
    > right?
    >
    
    Yes, I think so. The only thing the patch expects is a way to rollback
    the sequence changes if the transaction rolls back during the initial
    sync. But I am not sure if we need such a behavior. The discussion for
    the same is in progress. Let's wait for the outcome.
    
    > > Now, say we don't want to maintain the state of sequences for initial
    > > sync at all then after the error how will we detect if there are any
    > > pending sequences to be synced? One possibility is that we maintain a
    > > subscription level flag 'subsequencesync' in 'pg_subscription' to
    > > indicate whether sequences need sync. This flag would indicate whether
    > > to sync all the sequences in pg_susbcription_rel. This would mean that
    > > if there is an error while syncing the sequences we will resync all
    > > the sequences again. This could be acceptable considering the chances
    > > of error during sequence sync are low.
    >
    > There could be multiple subscriptions to a single database that point
    > to the same set of sequences.  Is there any conflict issue to worry
    > about here?
    >
    
    I don't think so. In the worst case, the same value would be copied
    twice. The same scenario in case of tables could lead to duplicate
    data or unique key violation ERRORs which is much worse. So, I expect
    users to be careful about the same.
    
    > > The benefit is that both the
    > > REFRESH PUBLICATION SEQUENCES and CREATE SUBSCRIPTION can use the same
    > > idea and sync all sequences without needing a new relfilenode. Users
    > > can always refer 'subsequencesync' flag in 'pg_subscription' to see if
    > > all the sequences are synced after executing the command.
    >
    > That would be cheaper, indeed.  Isn't a boolean too limiting?
    >
    
    In this idea, we only need a flag to say whether the sequence sync is
    required or not.
    
    > Isn't that something you'd want to track with a LSN as "the point in
    > WAL where all the sequences have been synced"?
    >
    
    It won't be any better for the required purpose because after CREATE
    SUBSCRIPTION, if REFERESH wants to toggle the flag to indicate the
    sequences need sync again then using LSN would mean we need to set it
    to Invalid value.
    
    > The approach of doing all the sync work from the subscriber, while
    > having a command that can be kicked from the subscriber side is a good
    > user experience.
    >
    
    Thank you for endorsing the idea.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  50. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-06-18T01:59:29Z

    On Fri, Jun 14, 2024 at 4:04 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Jun 13, 2024 at 6:14 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Thu, Jun 13, 2024 at 7:06 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Thu, Jun 13, 2024 at 1:09 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > > >
    > > > > On Wed, Jun 12, 2024 at 6:59 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > >
    > > > > >
    > > > > > Yeah, starting with a single worker sounds good for now. Do you think
    > > > > > we should sync all the sequences in a single transaction or have some
    > > > > > threshold value above which a different transaction would be required
    > > > > > or maybe a different sequence sync worker altogether? Now, having
    > > > > > multiple sequence-sync workers requires some synchronization so that
    > > > > > only a single worker is allocated for one sequence.
    > > > > >
    > > > > > The simplest thing is to use a single sequence sync worker that syncs
    > > > > > all sequences in one transaction but with a large number of sequences,
    > > > > > it could be inefficient. OTOH, I am not sure if it would be a problem
    > > > > > in reality.
    > > > >
    > > > > I think that we can start with using a single worker and one
    > > > > transaction, and measure the performance with a large number of
    > > > > sequences.
    > > > >
    > > >
    > > > Fair enough. However, this raises the question Dilip and Vignesh are
    > > > discussing whether we need a new relfilenode for sequence update even
    > > > during initial sync? As per my understanding, the idea is that similar
    > > > to tables, the CREATE SUBSCRIPTION command (with copy_data = true)
    > > > will create the new sequence entries in pg_subscription_rel with the
    > > > state as 'i'. Then the sequence-sync worker would start a transaction
    > > > and one-by-one copy the latest sequence values for each sequence (that
    > > > has state as 'i' in pg_subscription_rel) and mark its state as ready
    > > > 'r' and commit the transaction. Now if there is an error during this
    > > > operation it will restart the entire operation. The idea of creating a
    > > > new relfilenode is to handle the error so that if there is a rollback,
    > > > the sequence state will be rolled back to 'i' and the sequence value
    > > > will also be rolled back. The other option could be that we update the
    > > > sequence value without a new relfilenode and if the transaction rolled
    > > > back then only the sequence's state will be rolled back to 'i'. This
    > > > would work with a minor inconsistency that sequence values will be
    > > > up-to-date even when the sequence state is 'i' in pg_subscription_rel.
    > > > I am not sure if that matters because anyway, they can quickly be
    > > > out-of-sync with the publisher again.
    > >
    > > I think it would be fine in many cases even if the sequence value is
    > > up-to-date even when the sequence state is 'i' in pg_subscription_rel.
    > > But the case we would like to avoid is where suppose the sequence-sync
    > > worker does both synchronizing sequence values and updating the
    > > sequence states for all sequences in one transaction, and if there is
    > > an error we end up retrying the synchronization for all sequences.
    > >
    >
    > The one idea to avoid this is to update sequences in chunks (say 100
    > or some threshold number of sequences in one transaction). Then we
    > would only redo the sync for the last and pending set of sequences.
    
    That could be one idea.
    
    >
    > > >
    > > > Now, say we don't want to maintain the state of sequences for initial
    > > > sync at all then after the error how will we detect if there are any
    > > > pending sequences to be synced? One possibility is that we maintain a
    > > > subscription level flag 'subsequencesync' in 'pg_subscription' to
    > > > indicate whether sequences need sync. This flag would indicate whether
    > > > to sync all the sequences in pg_susbcription_rel. This would mean that
    > > > if there is an error while syncing the sequences we will resync all
    > > > the sequences again. This could be acceptable considering the chances
    > > > of error during sequence sync are low. The benefit is that both the
    > > > REFRESH PUBLICATION SEQUENCES and CREATE SUBSCRIPTION can use the same
    > > > idea and sync all sequences without needing a new relfilenode. Users
    > > > can always refer 'subsequencesync' flag in 'pg_subscription' to see if
    > > > all the sequences are synced after executing the command.
    > >
    > > I think that REFRESH PUBLICATION {SEQUENCES} can be executed even
    > > while the sequence-sync worker is synchronizing sequences. In this
    > > case, the worker might not see new sequences added by the concurrent
    > > REFRESH PUBLICATION {SEQUENCES} command since it's already running.
    > > The worker could end up marking the subsequencesync as completed while
    > > not synchronizing these new sequences.
    > >
    >
    > This is possible but we could avoid REFRESH PUBLICATION {SEQUENCES} by
    > not allowing to change the subsequencestate during the time
    > sequence-worker is syncing the sequences. This could be restrictive
    > but there doesn't seem to be cases where user would like to
    > immediately refresh sequences after creating the subscription.
    
    I'm concerned that users would not be able to add sequences during the
    time the sequence-worker is syncing the sequences. For example,
    suppose we have 10000 sequences and execute REFRESH PUBLICATION
    {SEQUENCES} to synchronize 10000 sequences. Now if we add one sequence
    to the publication and want to synchronize it to the subscriber, we
    have to wait for the current REFRESH PUBLICATION {SEQUENCES} to
    complete, and then execute it again, synchronizing 10001 sequences,
    instead of synchronizing only the new one.
    
    >
    > > >
    > > > > > > Or yet another idea I came up with is that a tablesync worker will
    > > > > > > synchronize both the table and sequences owned by the table. That is,
    > > > > > > after the tablesync worker caught up with the apply worker, the
    > > > > > > tablesync worker synchronizes sequences associated with the target
    > > > > > > table as well. One benefit would be that at the time of initial table
    > > > > > > sync being completed, the table and its sequence data are consistent.
    > > > >
    > > > > Correction; it's not guaranteed that the sequence data and table data
    > > > > are consistent even in this case since the tablesync worker could get
    > > > > on-disk sequence data that might have already been updated.
    > > > >
    > > >
    > > > The benefit of this approach is not clear to me. Our aim is to sync
    > > > all sequences before the upgrade, so not sure if this helps because
    > > > anyway both table values and corresponding sequences can again be
    > > > out-of-sync very quickly.
    > >
    > > Right.
    > >
    > > Given that our aim is to sync all sequences before the upgrade, do we
    > > need to synchronize sequences even at CREATE SUBSCRIPTION time? In
    > > cases where there are a large number of sequences, synchronizing
    > > sequences in addition to tables could be overhead and make less sense,
    > > because sequences can again be out-of-sync quickly and typically
    > > CREATE SUBSCRIPTION is not created just before the upgrade.
    > >
    >
    > I think for the upgrade one should be creating a subscription just
    > before the upgrade. Isn't something similar is done even in the
    > upgrade steps you shared once [1]?
    
    I might be missing something but in the blog post they created
    subscriptions in various ways, waited for the initial table data sync
    to complete, and then set the sequence values with a buffer based on
    the old cluster. What I imagined with this sequence synchronization
    feature is that after the initial table sync completes, we stop to
    execute further transactions on the publisher, synchronize sequences
    using REFRESH PUBLICATION {SEQUENCES}, and resume the application to
    execute transactions on the subscriber. So a subscription would be
    created just before the upgrade, but sequence synchronization would
    not necessarily happen at the same time of the initial table data
    synchronization.
    
    > Typically users should get all the
    > data from the publisher before the upgrade of the publisher via
    > creating a subscription. Also, it would be better to keep the
    > implementation of sequences close to tables wherever possible. Having
    > said that, I understand your point as well and if you strongly feel
    > that we don't need to sync sequences at the time of CREATE
    > SUBSCRIPTION and others also don't see any problem with it then we can
    > consider that as well.
    
    I see your point that it's better to keep the implementation of
    sequences close to the table one. So I agree that we can start with
    this approach, and we will see how it works in practice and consider
    other options later.
    
    >
    > > > >
    > > >
    > > > Do you mean that sync the sequences during the REFRESH PUBLICATION
    > > > SEQUENCES command itself? If so, there is an argument that we can do
    > > > the same during CREATE SUBSCRIPTION. It would be beneficial to keep
    > > > the method to sync the sequences same for both the CREATE and REFRESH
    > > > commands. I have speculated on one idea above and would be happy to
    > > > see your thoughts.
    > >
    > > I meant that the REFRESH PUBLICATION SEQUENCES command updates all
    > > sequence states in pg_subscription_rel to 'init' state, and the
    > > sequence-sync worker can do the synchronization work. We use the same
    > > method for both the CREATE SUBSCRIPTION and REFRESH PUBLICATION
    > > {SEQUENCES} commands.
    > >
    >
    > Marking the state as 'init' when we would have already synced the
    > sequences sounds a bit odd but otherwise, this could also work if we
    > accept that even if the sequences are synced and value could remain in
    > 'init' state (on rollbacks).
    
    I mean that it's just for identifying sequences that need to be
    synced. With the idea of using sequence states in pg_subscription_rel,
    the REFRESH PUBLICATION SEQUENCES command needs to change states to
    something so that the sequence-sync worker can identify which sequence
    needs to be synced. If 'init' sounds odd, we can invent a new state
    for sequences, say 'needs-to-be-syned'.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  51. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-18T10:40:25Z

    On Tue, Jun 18, 2024 at 7:30 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Fri, Jun 14, 2024 at 4:04 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Thu, Jun 13, 2024 at 6:14 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > >
    > >
    > > > >
    > > > > Now, say we don't want to maintain the state of sequences for initial
    > > > > sync at all then after the error how will we detect if there are any
    > > > > pending sequences to be synced? One possibility is that we maintain a
    > > > > subscription level flag 'subsequencesync' in 'pg_subscription' to
    > > > > indicate whether sequences need sync. This flag would indicate whether
    > > > > to sync all the sequences in pg_susbcription_rel. This would mean that
    > > > > if there is an error while syncing the sequences we will resync all
    > > > > the sequences again. This could be acceptable considering the chances
    > > > > of error during sequence sync are low. The benefit is that both the
    > > > > REFRESH PUBLICATION SEQUENCES and CREATE SUBSCRIPTION can use the same
    > > > > idea and sync all sequences without needing a new relfilenode. Users
    > > > > can always refer 'subsequencesync' flag in 'pg_subscription' to see if
    > > > > all the sequences are synced after executing the command.
    > > >
    > > > I think that REFRESH PUBLICATION {SEQUENCES} can be executed even
    > > > while the sequence-sync worker is synchronizing sequences. In this
    > > > case, the worker might not see new sequences added by the concurrent
    > > > REFRESH PUBLICATION {SEQUENCES} command since it's already running.
    > > > The worker could end up marking the subsequencesync as completed while
    > > > not synchronizing these new sequences.
    > > >
    > >
    > > This is possible but we could avoid REFRESH PUBLICATION {SEQUENCES} by
    > > not allowing to change the subsequencestate during the time
    > > sequence-worker is syncing the sequences. This could be restrictive
    > > but there doesn't seem to be cases where user would like to
    > > immediately refresh sequences after creating the subscription.
    >
    > I'm concerned that users would not be able to add sequences during the
    > time the sequence-worker is syncing the sequences. For example,
    > suppose we have 10000 sequences and execute REFRESH PUBLICATION
    > {SEQUENCES} to synchronize 10000 sequences. Now if we add one sequence
    > to the publication and want to synchronize it to the subscriber, we
    > have to wait for the current REFRESH PUBLICATION {SEQUENCES} to
    > complete, and then execute it again, synchronizing 10001 sequences,
    > instead of synchronizing only the new one.
    >
    
    I see your point and it could hurt such scenarios even though they
    won't be frequent. So, let's focus on our other approach of
    maintaining the flag at a per-sequence level in pg_subscription_rel.
    
    > >
    > > > >
    > > > > > > > Or yet another idea I came up with is that a tablesync worker will
    > > > > > > > synchronize both the table and sequences owned by the table. That is,
    > > > > > > > after the tablesync worker caught up with the apply worker, the
    > > > > > > > tablesync worker synchronizes sequences associated with the target
    > > > > > > > table as well. One benefit would be that at the time of initial table
    > > > > > > > sync being completed, the table and its sequence data are consistent.
    > > > > >
    > > > > > Correction; it's not guaranteed that the sequence data and table data
    > > > > > are consistent even in this case since the tablesync worker could get
    > > > > > on-disk sequence data that might have already been updated.
    > > > > >
    > > > >
    > > > > The benefit of this approach is not clear to me. Our aim is to sync
    > > > > all sequences before the upgrade, so not sure if this helps because
    > > > > anyway both table values and corresponding sequences can again be
    > > > > out-of-sync very quickly.
    > > >
    > > > Right.
    > > >
    > > > Given that our aim is to sync all sequences before the upgrade, do we
    > > > need to synchronize sequences even at CREATE SUBSCRIPTION time? In
    > > > cases where there are a large number of sequences, synchronizing
    > > > sequences in addition to tables could be overhead and make less sense,
    > > > because sequences can again be out-of-sync quickly and typically
    > > > CREATE SUBSCRIPTION is not created just before the upgrade.
    > > >
    > >
    > > I think for the upgrade one should be creating a subscription just
    > > before the upgrade. Isn't something similar is done even in the
    > > upgrade steps you shared once [1]?
    >
    > I might be missing something but in the blog post they created
    > subscriptions in various ways, waited for the initial table data sync
    > to complete, and then set the sequence values with a buffer based on
    > the old cluster. What I imagined with this sequence synchronization
    > feature is that after the initial table sync completes, we stop to
    > execute further transactions on the publisher, synchronize sequences
    > using REFRESH PUBLICATION {SEQUENCES}, and resume the application to
    > execute transactions on the subscriber. So a subscription would be
    > created just before the upgrade, but sequence synchronization would
    > not necessarily happen at the same time of the initial table data
    > synchronization.
    >
    
    It depends on the exact steps of the upgrade. For example, if one
    stops the publisher before adding sequences to a subscription either
    via create subscription or alter subscription add/set command then
    there won't be a need for a separate refresh but OTOH, if one follows
    the steps you mentioned then the refresh would be required. As you are
    okay, with syncing the sequences while creating a subscription in the
    below part of the email, there is not much point in arguing about this
    further.
    
    > > Typically users should get all the
    > > data from the publisher before the upgrade of the publisher via
    > > creating a subscription. Also, it would be better to keep the
    > > implementation of sequences close to tables wherever possible. Having
    > > said that, I understand your point as well and if you strongly feel
    > > that we don't need to sync sequences at the time of CREATE
    > > SUBSCRIPTION and others also don't see any problem with it then we can
    > > consider that as well.
    >
    > I see your point that it's better to keep the implementation of
    > sequences close to the table one. So I agree that we can start with
    > this approach, and we will see how it works in practice and consider
    > other options later.
    >
    
    makes sense.
    
    > >
    > > Marking the state as 'init' when we would have already synced the
    > > sequences sounds a bit odd but otherwise, this could also work if we
    > > accept that even if the sequences are synced and value could remain in
    > > 'init' state (on rollbacks).
    >
    > I mean that it's just for identifying sequences that need to be
    > synced. With the idea of using sequence states in pg_subscription_rel,
    > the REFRESH PUBLICATION SEQUENCES command needs to change states to
    > something so that the sequence-sync worker can identify which sequence
    > needs to be synced. If 'init' sounds odd, we can invent a new state
    > for sequences, say 'needs-to-be-syned'.
    >
    
    Agreed and I am not sure which is better because there is a value in
    keeping the state name the same for both sequences and tables. We
    probably need more comments in code and doc updates to make the
    behavior clear. We can start with the sequence state as 'init' for
    'needs-to-be-sycned' and 'ready' for 'synced' and can change if others
    feel so during the review.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  52. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-19T15:03:37Z

    On Tue, 18 Jun 2024 at 16:10, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    >
    > Agreed and I am not sure which is better because there is a value in
    > keeping the state name the same for both sequences and tables. We
    > probably need more comments in code and doc updates to make the
    > behavior clear. We can start with the sequence state as 'init' for
    > 'needs-to-be-sycned' and 'ready' for 'synced' and can change if others
    > feel so during the review.
    
    Here is a patch which does the sequence synchronization in the
    following lines from the above discussion:
    This commit introduces sequence synchronization during 1) creation of
    subscription for initial sync of sequences 2) refresh publication to
    synchronize the sequences for the newly created sequences 3) refresh
    publication sequences for synchronizing all the sequences.
    1) During subscription creation with CREATE SUBSCRIPTION (no syntax change):
       - The subscriber retrieves sequences associated with publications.
       - Sequences  are added in the 'init' state to the pg_subscription_rel table.
       - Sequence synchronization worker will be started if there are any
    sequences to be synchronized
       - A new sequence synchronization worker handles synchronization in
    batches of 100 sequences:
         a) Retrieves sequence values using pg_sequence_state from the publisher.
         b) Sets sequence values accordingly.
         c) Updates sequence state to 'READY' in pg_susbcripion_rel
         d) Commits batches of 100 synchronized sequences.
    2) Refreshing sequences with ALTER SUBSCRIPTION ... REFRESH
    PUBLICATION (no syntax change):
       - Stale sequences are removed from pg_subscription_rel.
       - Newly added sequences in the publisher are added in 'init' state
    to pg_subscription_rel.
       - Sequence synchronization will be done by sequence sync worker as
    listed in subscription creation process.
       - Sequence synchronization occurs for newly added sequences only.
    3) Introduce new command ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES  for refreshing all sequences:
       - Removes stale sequences and adds newly added sequences from the
    publisher to pg_subscription_rel.
       - Resets all sequences in pg_subscription_rel to 'init' state.
       - Initiates sequence synchronization for all sequences by sequence
    sync worker as listed in subscription creation process.
    
    Regards,
    Vignesh
    
  53. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-20T12:53:34Z

    On Wed, 19 Jun 2024 at 20:33, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 18 Jun 2024 at 16:10, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > >
    > > Agreed and I am not sure which is better because there is a value in
    > > keeping the state name the same for both sequences and tables. We
    > > probably need more comments in code and doc updates to make the
    > > behavior clear. We can start with the sequence state as 'init' for
    > > 'needs-to-be-sycned' and 'ready' for 'synced' and can change if others
    > > feel so during the review.
    >
    > Here is a patch which does the sequence synchronization in the
    > following lines from the above discussion:
    > This commit introduces sequence synchronization during 1) creation of
    > subscription for initial sync of sequences 2) refresh publication to
    > synchronize the sequences for the newly created sequences 3) refresh
    > publication sequences for synchronizing all the sequences.
    > 1) During subscription creation with CREATE SUBSCRIPTION (no syntax change):
    >    - The subscriber retrieves sequences associated with publications.
    >    - Sequences  are added in the 'init' state to the pg_subscription_rel table.
    >    - Sequence synchronization worker will be started if there are any
    > sequences to be synchronized
    >    - A new sequence synchronization worker handles synchronization in
    > batches of 100 sequences:
    >      a) Retrieves sequence values using pg_sequence_state from the publisher.
    >      b) Sets sequence values accordingly.
    >      c) Updates sequence state to 'READY' in pg_susbcripion_rel
    >      d) Commits batches of 100 synchronized sequences.
    > 2) Refreshing sequences with ALTER SUBSCRIPTION ... REFRESH
    > PUBLICATION (no syntax change):
    >    - Stale sequences are removed from pg_subscription_rel.
    >    - Newly added sequences in the publisher are added in 'init' state
    > to pg_subscription_rel.
    >    - Sequence synchronization will be done by sequence sync worker as
    > listed in subscription creation process.
    >    - Sequence synchronization occurs for newly added sequences only.
    > 3) Introduce new command ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > SEQUENCES  for refreshing all sequences:
    >    - Removes stale sequences and adds newly added sequences from the
    > publisher to pg_subscription_rel.
    >    - Resets all sequences in pg_subscription_rel to 'init' state.
    >    - Initiates sequence synchronization for all sequences by sequence
    > sync worker as listed in subscription creation process.
    
    Here is an updated patch with a few fixes to remove an unused
    function, changed a few references of table to sequence and added one
    CHECK_FOR_INTERRUPTS in the sequence sync worker loop.
    
    Regards,
    Vignesh
    
  54. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-06-20T13:14:50Z

    On Wed, Jun 19, 2024 at 8:33 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 18 Jun 2024 at 16:10, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > >
    > > Agreed and I am not sure which is better because there is a value in
    > > keeping the state name the same for both sequences and tables. We
    > > probably need more comments in code and doc updates to make the
    > > behavior clear. We can start with the sequence state as 'init' for
    > > 'needs-to-be-sycned' and 'ready' for 'synced' and can change if others
    > > feel so during the review.
    >
    > Here is a patch which does the sequence synchronization in the
    > following lines from the above discussion:
    >
    
    Thanks for summarizing the points discussed. I would like to confirm
    whether the patch replicates new sequences that are created
    implicitly/explicitly for a publication defined as ALL SEQUENCES.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  55. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-24T07:27:09Z

    On Thu, 20 Jun 2024 at 18:45, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Wed, Jun 19, 2024 at 8:33 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Tue, 18 Jun 2024 at 16:10, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > >
    > > > Agreed and I am not sure which is better because there is a value in
    > > > keeping the state name the same for both sequences and tables. We
    > > > probably need more comments in code and doc updates to make the
    > > > behavior clear. We can start with the sequence state as 'init' for
    > > > 'needs-to-be-sycned' and 'ready' for 'synced' and can change if others
    > > > feel so during the review.
    > >
    > > Here is a patch which does the sequence synchronization in the
    > > following lines from the above discussion:
    > >
    >
    > Thanks for summarizing the points discussed. I would like to confirm
    > whether the patch replicates new sequences that are created
    > implicitly/explicitly for a publication defined as ALL SEQUENCES.
    
    Currently, FOR ALL SEQUENCES publication both explicitly created
    sequences and implicitly created sequences will be synchronized during
    the creation of subscriptions (using CREATE SUBSCRIPTION) and
    refreshing publication sequences(using ALTER SUBSCRIPTION ... REFRESH
    PUBLICATION SEQUENCES).
    Therefore, the explicitly created sequence seq1:
    CREATE SEQUENCE seq1;
    and the implicitly created sequence seq_test2_c2_seq for seq_test2 table:
    CREATE TABLE seq_test2 (c1 int, c2 SERIAL);
    will both be synchronized.
    
    Regards,
    Vignesh
    
    
    
    
  56. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2024-06-25T12:22:54Z

    On Thu, 20 Jun 2024 at 18:24, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 19 Jun 2024 at 20:33, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Tue, 18 Jun 2024 at 16:10, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > >
    > > > Agreed and I am not sure which is better because there is a value in
    > > > keeping the state name the same for both sequences and tables. We
    > > > probably need more comments in code and doc updates to make the
    > > > behavior clear. We can start with the sequence state as 'init' for
    > > > 'needs-to-be-sycned' and 'ready' for 'synced' and can change if others
    > > > feel so during the review.
    > >
    > > Here is a patch which does the sequence synchronization in the
    > > following lines from the above discussion:
    > > This commit introduces sequence synchronization during 1) creation of
    > > subscription for initial sync of sequences 2) refresh publication to
    > > synchronize the sequences for the newly created sequences 3) refresh
    > > publication sequences for synchronizing all the sequences.
    > > 1) During subscription creation with CREATE SUBSCRIPTION (no syntax change):
    > >    - The subscriber retrieves sequences associated with publications.
    > >    - Sequences  are added in the 'init' state to the pg_subscription_rel table.
    > >    - Sequence synchronization worker will be started if there are any
    > > sequences to be synchronized
    > >    - A new sequence synchronization worker handles synchronization in
    > > batches of 100 sequences:
    > >      a) Retrieves sequence values using pg_sequence_state from the publisher.
    > >      b) Sets sequence values accordingly.
    > >      c) Updates sequence state to 'READY' in pg_susbcripion_rel
    > >      d) Commits batches of 100 synchronized sequences.
    > > 2) Refreshing sequences with ALTER SUBSCRIPTION ... REFRESH
    > > PUBLICATION (no syntax change):
    > >    - Stale sequences are removed from pg_subscription_rel.
    > >    - Newly added sequences in the publisher are added in 'init' state
    > > to pg_subscription_rel.
    > >    - Sequence synchronization will be done by sequence sync worker as
    > > listed in subscription creation process.
    > >    - Sequence synchronization occurs for newly added sequences only.
    > > 3) Introduce new command ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > > SEQUENCES  for refreshing all sequences:
    > >    - Removes stale sequences and adds newly added sequences from the
    > > publisher to pg_subscription_rel.
    > >    - Resets all sequences in pg_subscription_rel to 'init' state.
    > >    - Initiates sequence synchronization for all sequences by sequence
    > > sync worker as listed in subscription creation process.
    >
    > Here is an updated patch with a few fixes to remove an unused
    > function, changed a few references of table to sequence and added one
    > CHECK_FOR_INTERRUPTS in the sequence sync worker loop.
    
    Hi Vignesh,
    
    I have reviewed the patches and I have following comments:
    
    ===== tablesync.c ======
    1. process_syncing_sequences_for_apply can crash with:
    2024-06-21 15:25:17.208 IST [3681269] LOG:  logical replication apply
    worker for subscription "test1" has started
    2024-06-21 15:28:10.127 IST [3682329] LOG:  logical replication
    sequences synchronization worker for subscription "test1" has started
    2024-06-21 15:28:10.146 IST [3682329] LOG:  logical replication
    synchronization for subscription "test1", sequence "s1" has finished
    2024-06-21 15:28:10.149 IST [3682329] LOG:  logical replication
    synchronization for subscription "test1", sequence "s2" has finished
    2024-06-21 15:28:10.149 IST [3682329] LOG:  logical replication
    sequences synchronization worker for subscription "test1" has finished
    2024-06-21 15:29:53.535 IST [3682767] LOG:  logical replication
    sequences synchronization worker for subscription "test1" has started
    TRAP: failed Assert("nestLevel > 0 && (nestLevel <= GUCNestLevel ||
    (nestLevel == GUCNestLevel + 1 && !isCommit))"), File: "guc.c", Line:
    2273, PID: 3682767
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (ExceptionalCondition+0xbb)[0x5b2a61861c99]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (AtEOXact_GUC+0x7b)[0x5b2a618bddfa]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (RestoreUserContext+0xc7)[0x5b2a618a6937]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (+0x1ff7dfa)[0x5b2a61115dfa]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (+0x1ff7eb4)[0x5b2a61115eb4]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (SequencesyncWorkerMain+0x33)[0x5b2a61115fe7]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (BackgroundWorkerMain+0x4ad)[0x5b2a61029cae]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (postmaster_child_launch+0x236)[0x5b2a6102fb36]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (+0x1f1d12a)[0x5b2a6103b12a]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (+0x1f1df0f)[0x5b2a6103bf0f]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (+0x1f1bf71)[0x5b2a61039f71]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (+0x1f16f73)[0x5b2a61034f73]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (PostmasterMain+0x18fb)[0x5b2a61034445]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (+0x1ab1ab8)[0x5b2a60bcfab8]
    /lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x7b76bc629d90]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x7b76bc629e40]
    postgres: logical replication sequencesync worker for subscription
    16389 sync 0 (_start+0x25)[0x5b2a601491a5]
    
    Analysis:
    Suppose there are two sequences (s1, s2) on publisher.
    SO, during initial sync.
    in loop,
    + foreach(lc, table_states_not_ready)
    
    table_states_not_ready -> it contains both s1 and s2.
    So, for s1 a sequence sync will be started. It will sync all sequences
    and the sequence sync worker will exit.
    Now, for s2 again a sequence sync will start. It will give the above error.
    
    Is this loop required? Instead we can just use a bool like
    'is_any_sequence_not_ready'. Thoughts?
    
    ===== sequencesync.c =====
    2. function name should be 'LogicalRepSyncSequences' instead of
    'LogicalRepSyncSeqeunces'
    
    3. In function 'LogicalRepSyncSeqeunces'
        sequencerel = table_open(seqinfo->relid, RowExclusiveLock);\
        There is a extra '\' symbol
    
    4. In function LogicalRepSyncSeqeunces:
    + ereport(LOG,
    + errmsg("logical replication synchronization for subscription \"%s\",
    sequence \"%s\" has finished",
    +   get_subscription_name(subid, false), RelationGetRelationName(sequencerel)));
    + table_close(sequencerel, NoLock);
    +
    + currseq++;
    +
    + if (currseq % MAX_SEQUENCES_SYNC_PER_BATCH == 0 || currseq ==
    list_length(sequences))
    + CommitTransactionCommand();
    
    
    The above message gets logged even if the changes are not committed.
    Suppose the sequence worker exits before commit due to some reason.
    Thought the log will show that sequence is synced, the sequence will
    be in 'init' state. I think this is not desirable.
    Maybe we should log the synced sequences at commit time? Thoughts?
    
    ===== General ====
    5. We can use other macros like 'foreach_ptr' instead of 'foreach'
    
    Thanks and Regards,
    Shlok Kyal
    
    
    
    
  57. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-06-25T15:39:17Z

    On Tue, 25 Jun 2024 at 17:53, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    >
    > On Thu, 20 Jun 2024 at 18:24, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Wed, 19 Jun 2024 at 20:33, vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Tue, 18 Jun 2024 at 16:10, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > > >
    > > > > Agreed and I am not sure which is better because there is a value in
    > > > > keeping the state name the same for both sequences and tables. We
    > > > > probably need more comments in code and doc updates to make the
    > > > > behavior clear. We can start with the sequence state as 'init' for
    > > > > 'needs-to-be-sycned' and 'ready' for 'synced' and can change if others
    > > > > feel so during the review.
    > > >
    > > > Here is a patch which does the sequence synchronization in the
    > > > following lines from the above discussion:
    > > > This commit introduces sequence synchronization during 1) creation of
    > > > subscription for initial sync of sequences 2) refresh publication to
    > > > synchronize the sequences for the newly created sequences 3) refresh
    > > > publication sequences for synchronizing all the sequences.
    > > > 1) During subscription creation with CREATE SUBSCRIPTION (no syntax change):
    > > >    - The subscriber retrieves sequences associated with publications.
    > > >    - Sequences  are added in the 'init' state to the pg_subscription_rel table.
    > > >    - Sequence synchronization worker will be started if there are any
    > > > sequences to be synchronized
    > > >    - A new sequence synchronization worker handles synchronization in
    > > > batches of 100 sequences:
    > > >      a) Retrieves sequence values using pg_sequence_state from the publisher.
    > > >      b) Sets sequence values accordingly.
    > > >      c) Updates sequence state to 'READY' in pg_susbcripion_rel
    > > >      d) Commits batches of 100 synchronized sequences.
    > > > 2) Refreshing sequences with ALTER SUBSCRIPTION ... REFRESH
    > > > PUBLICATION (no syntax change):
    > > >    - Stale sequences are removed from pg_subscription_rel.
    > > >    - Newly added sequences in the publisher are added in 'init' state
    > > > to pg_subscription_rel.
    > > >    - Sequence synchronization will be done by sequence sync worker as
    > > > listed in subscription creation process.
    > > >    - Sequence synchronization occurs for newly added sequences only.
    > > > 3) Introduce new command ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > > > SEQUENCES  for refreshing all sequences:
    > > >    - Removes stale sequences and adds newly added sequences from the
    > > > publisher to pg_subscription_rel.
    > > >    - Resets all sequences in pg_subscription_rel to 'init' state.
    > > >    - Initiates sequence synchronization for all sequences by sequence
    > > > sync worker as listed in subscription creation process.
    > >
    > > Here is an updated patch with a few fixes to remove an unused
    > > function, changed a few references of table to sequence and added one
    > > CHECK_FOR_INTERRUPTS in the sequence sync worker loop.
    >
    > Hi Vignesh,
    >
    > I have reviewed the patches and I have following comments:
    >
    > ===== tablesync.c ======
    > 1. process_syncing_sequences_for_apply can crash with:
    > 2024-06-21 15:25:17.208 IST [3681269] LOG:  logical replication apply
    > worker for subscription "test1" has started
    > 2024-06-21 15:28:10.127 IST [3682329] LOG:  logical replication
    > sequences synchronization worker for subscription "test1" has started
    > 2024-06-21 15:28:10.146 IST [3682329] LOG:  logical replication
    > synchronization for subscription "test1", sequence "s1" has finished
    > 2024-06-21 15:28:10.149 IST [3682329] LOG:  logical replication
    > synchronization for subscription "test1", sequence "s2" has finished
    > 2024-06-21 15:28:10.149 IST [3682329] LOG:  logical replication
    > sequences synchronization worker for subscription "test1" has finished
    > 2024-06-21 15:29:53.535 IST [3682767] LOG:  logical replication
    > sequences synchronization worker for subscription "test1" has started
    > TRAP: failed Assert("nestLevel > 0 && (nestLevel <= GUCNestLevel ||
    > (nestLevel == GUCNestLevel + 1 && !isCommit))"), File: "guc.c", Line:
    > 2273, PID: 3682767
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (ExceptionalCondition+0xbb)[0x5b2a61861c99]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (AtEOXact_GUC+0x7b)[0x5b2a618bddfa]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (RestoreUserContext+0xc7)[0x5b2a618a6937]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (+0x1ff7dfa)[0x5b2a61115dfa]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (+0x1ff7eb4)[0x5b2a61115eb4]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (SequencesyncWorkerMain+0x33)[0x5b2a61115fe7]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (BackgroundWorkerMain+0x4ad)[0x5b2a61029cae]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (postmaster_child_launch+0x236)[0x5b2a6102fb36]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (+0x1f1d12a)[0x5b2a6103b12a]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (+0x1f1df0f)[0x5b2a6103bf0f]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (+0x1f1bf71)[0x5b2a61039f71]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (+0x1f16f73)[0x5b2a61034f73]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (PostmasterMain+0x18fb)[0x5b2a61034445]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (+0x1ab1ab8)[0x5b2a60bcfab8]
    > /lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x7b76bc629d90]
    > /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x7b76bc629e40]
    > postgres: logical replication sequencesync worker for subscription
    > 16389 sync 0 (_start+0x25)[0x5b2a601491a5]
    >
    > Analysis:
    > Suppose there are two sequences (s1, s2) on publisher.
    > SO, during initial sync.
    > in loop,
    > + foreach(lc, table_states_not_ready)
    >
    > table_states_not_ready -> it contains both s1 and s2.
    > So, for s1 a sequence sync will be started. It will sync all sequences
    > and the sequence sync worker will exit.
    > Now, for s2 again a sequence sync will start. It will give the above error.
    >
    > Is this loop required? Instead we can just use a bool like
    > 'is_any_sequence_not_ready'. Thoughts?
    >
    > ===== sequencesync.c =====
    > 2. function name should be 'LogicalRepSyncSequences' instead of
    > 'LogicalRepSyncSeqeunces'
    >
    > 3. In function 'LogicalRepSyncSeqeunces'
    >     sequencerel = table_open(seqinfo->relid, RowExclusiveLock);\
    >     There is a extra '\' symbol
    >
    > 4. In function LogicalRepSyncSeqeunces:
    > + ereport(LOG,
    > + errmsg("logical replication synchronization for subscription \"%s\",
    > sequence \"%s\" has finished",
    > +   get_subscription_name(subid, false), RelationGetRelationName(sequencerel)));
    > + table_close(sequencerel, NoLock);
    > +
    > + currseq++;
    > +
    > + if (currseq % MAX_SEQUENCES_SYNC_PER_BATCH == 0 || currseq ==
    > list_length(sequences))
    > + CommitTransactionCommand();
    >
    >
    > The above message gets logged even if the changes are not committed.
    > Suppose the sequence worker exits before commit due to some reason.
    > Thought the log will show that sequence is synced, the sequence will
    > be in 'init' state. I think this is not desirable.
    > Maybe we should log the synced sequences at commit time? Thoughts?
    >
    > ===== General ====
    > 5. We can use other macros like 'foreach_ptr' instead of 'foreach'
    
    Thanks for the comments, the attached patch has the fixes for the same.
    
    Regards,
    Vignesh
    
  58. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-06-26T09:10:39Z

    Here are my initial review comments for the first patch v20240625-0001.
    
    ======
    General
    
    1. Missing docs?
    
    Section 9.17. "Sequence Manipulation Functions" [1] describes some
    functions. Shouldn't your new function be documented here also?
    
    ~~~
    
    2. Missing tests?
    
    Shouldn't there be some test code that at least executes your new
    pg_sequence_state function to verify that sane values are returned?
    
    ======
    Commit Message
    
    3.
    This patch introduces new functionalities to PostgreSQL:
    - pg_sequence_state allows retrieval of sequence values using LSN.
    - SetSequence enables updating sequences with user-specified values.
    
    ~
    
    3a.
    I didn't understand why this says "using LSN" because IIUC 'lsn' is an
    output parameter of that function. Don't you mean "... retrieval of
    sequence values including LSN"?
    
    ~
    
    3b.
    Does "user-specified" make sense? Is this going to be exposed to a
    user? How about just "specified"?
    
    ======
    src/backend/commands/sequence.c
    
    4. SetSequence:
    
    +void
    +SetSequence(Oid seq_relid, int64 value)
    
    Would 'new_last_value' be a better parameter name here?
    
    ~~~
    
    5.
    This new function logic looks pretty similar to the do_setval()
    function. Can you explain (maybe in the function comment) some info
    about how and why it differs from that other function?
    
    ~~~
    
    6.
    I saw that RelationNeedsWAL() is called 2 times. It may make no sense,
    but is it possible to assign that to a variable 1st time so you don't
    need to call it 2nd time within the critical section?
    
    ~~~
    
    NITPICK - remove junk (') char in comment
    
    NITPICK - missing periods (.) in multi-sentence comment
    
    ~~~
    
    7.
    -read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
    +read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple,
    +    XLogRecPtr *lsn)
    
    7a.
    The existing parameters were described in the function comment. So,
    the new 'lsn' parameter should be described here also.
    
    ~
    
    7b.
    Maybe the new parameter name should be 'lsn_res' or 'lsn_out' or
    similar to emphasise that this is a returned value.
    
    ~~
    
    NITPICK - tweaked comment. YMMV.
    
    ~~~
    
    8. pg_sequence_state:
    
    Should you give descriptions of the output parameters in the function
    header comment? Otherwise, where are they described so called knows
    what they mean?
    
    ~~~
    
    NITPICK - /relid/seq_relid/
    
    NITPICK - declare the variables in the same order as the output parameters
    
    NITPICK - An alternative to the memset for nulls is just to use static
    initialisation
    "bool nulls[4] = {false, false, false, false};"
    
    ======
    +extern void SetSequence(Oid seq_relid, int64 value);
    
    9.
    Would 'SetSequenceLastValue' be a better name for what this function is doing?
    
    ======
    
    99.
    See also my attached diff which is a top-up patch implementing those
    nitpicks mentioned above. Please apply any of these that you agree
    with.
    
    ======
    [1] https://www.postgresql.org/docs/devel/functions-sequence.html
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  59. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-01T07:27:22Z

    Here are some review comments for the patch v20240625-0002
    
    ======
    Commit Message
    
    1.
    This commit enhances logical replication by enabling the inclusion of all
    sequences in publications. This improvement facilitates seamless
    synchronization of sequence data during operations such as
    CREATE SUBSCRIPTION, REFRESH PUBLICATION, and REFRESH PUBLICATION SEQUENCES.
    
    ~
    
    Isn't this description getting ahead of the functionality a bit? For
    example, it talks about operations like REFRESH PUBLICATION SEQUENCES
    but AFAIK that syntax does not exist just yet.
    
    ~~~
    
    2.
    The commit message should mention that you are only introducing new
    syntax for "FOR ALL SEQUENCES" here, but syntax for "FOR SEQUENCE" is
    being deferred to some later patch. Without such a note it is not
    clear why the gram.y syntax and docs seemed only half done.
    
    ======
    doc/src/sgml/ref/create_publication.sgml
    
    3.
        <varlistentry id="sql-createpublication-params-for-all-tables">
         <term><literal>FOR ALL TABLES</literal></term>
    +    <term><literal>FOR ALL SEQUENCES</literal></term>
         <listitem>
          <para>
    -      Marks the publication as one that replicates changes for all tables in
    -      the database, including tables created in the future.
    +      Marks the publication as one that replicates changes for all tables or
    +      sequences in the database, including tables created in the future.
    
    It might be better here to keep descriptions for "ALL TABLES" and "ALL
    SEQUENCES" separated, otherwise the wording does not quite seem
    appropriate for sequences (e.g. where it says "including tables
    created in the future").
    
    ~~~
    
    NITPICK - missing spaces
    NITPICK - removed Oxford commas since previously there were none
    
    ~~~
    
    4.
    +   If <literal>FOR TABLE</literal>, <literal>FOR ALL TABLES</literal>,
    +   <literal>FOR ALL SEQUENCES</literal>,or <literal>FOR TABLES IN
    SCHEMA</literal>
    +   are not specified, then the publication starts out with an empty set of
    +   tables.  That is useful if tables or schemas are to be added later.
    
    It seems like "FOR ALL SEQUENCES" is out of place since it is jammed
    between other clauses referring to TABLES. Would it be better to
    mention SEQUENCES last in the list?
    
    ~~~
    
    5.
    +   rights on the table.  The <command>FOR ALL TABLES</command>,
    +   <command>FOR ALL SEQUENCES</command>, and
        <command>FOR TABLES IN SCHEMA</command> clauses require the invoking
    
    ditto of #4 above.
    
    ======
    src/backend/catalog/pg_publication.c
    
    GetAllSequencesPublicationRelations:
    
    NITPICK - typo /relation/relations/
    
    ======
    src/backend/commands/publicationcmds.c
    
    6.
    + foreach(lc, stmt->for_all_objects)
    + {
    + char    *val = strVal(lfirst(lc));
    +
    + if (strcmp(val, "tables") == 0)
    + for_all_tables = true;
    + else if (strcmp(val, "sequences") == 0)
    + for_all_sequences = true;
    + }
    
    Consider the foreach_ptr macro to slightly simplify this code.
    Actually, this whole logic seems cumbersome -- can’t the parser assign
    flags automatically. Please see my more detailed comment #10 below
    about this in gram.y
    
    ~~~
    
    7.
      /* FOR ALL TABLES requires superuser */
    - if (stmt->for_all_tables && !superuser())
    + if (for_all_tables && !superuser())
      ereport(ERROR,
      (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
      errmsg("must be superuser to create FOR ALL TABLES publication")));
    
    + /* FOR ALL SEQUENCES requires superuser */
    + if (for_all_sequences && !superuser())
    + ereport(ERROR,
    + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    + errmsg("must be superuser to create FOR ALL SEQUENCES publication")));
    +
    
    The current code is easy to read, but I wonder if it should try harder
    to share common code, or at least a common translatable message like
    "must be superuser to create %s publication".
    
    ~~~
    
    8.
    - else
    +
    + /*
    + * If the publication might have either tables or sequences (directly or
    + * through a schema), process that.
    + */
    + if (!for_all_tables || !for_all_sequences)
    
    I did not understand why this code cannot just say "else" like before,
    because the direct or through-schema syntax cannot be specified at the
    same time as "FOR ALL ...", so why is the more complicated condition
    necessary? Also, the similar code in AlterPublicationOptions() was not
    changed to be like this.
    
    ======
    src/backend/parser/gram.y
    
    9. comment
    
      *
      * CREATE PUBLICATION FOR ALL TABLES [WITH options]
      *
    + * CREATE PUBLICATION FOR ALL SEQUENCES [WITH options]
    + *
      * CREATE PUBLICATION FOR pub_obj [, ...] [WITH options]
    
    The comment is not quite correct because actually you are allowing
    simultaneous FOR ALL TABLES, SEQUENCES. It should be more like:
    
    CREATE PUBLICATION FOR ALL pub_obj_type [,...] [WITH options]
    
    pub_obj_type is one of:
    TABLES
    SEQUENCES
    
    ~~~
    
    10.
    +pub_obj_type: TABLES
    + { $$ = (Node *) makeString("tables"); }
    + | SEQUENCES
    + { $$ = (Node *) makeString("sequences"); }
    + ;
    +
    +pub_obj_type_list: pub_obj_type
    + { $$ = list_make1($1); }
    + | pub_obj_type_list ',' pub_obj_type
    + { $$ = lappend($1, $3); }
    + ;
    
    IIUC the only thing you need is a flag to say if FOR ALL TABLE is in
    effect and another flag to say if FOR ALL SEQUENCES is in effect. So,
    It seemed clunky to build up a temporary list of "tables" or
    "sequences" strings here, which is subsequently scanned by
    CreatePublication to be turned back into booleans.
    
    Can't we just change the CreatePublicationStmt field to have:
    
    A) a 'for_all_types' bitmask instead of a list:
    0x0000 means FOR ALL is not specified
    0x0001 means ALL TABLES
    0x0010 means ALL SEQUENCES
    
    Or, B) have 2 boolean fields ('for_all_tables' and 'for_all_sequences')
    
    ...where the gram.y code can be written to assign the flag/s values directly?
    
    ======
    src/bin/pg_dump/pg_dump.c
    
    11.
      if (pubinfo->puballtables)
      appendPQExpBufferStr(query, " FOR ALL TABLES");
    
    + if (pubinfo->puballsequences)
    + appendPQExpBufferStr(query, " FOR ALL SEQUENCES");
    +
    
    Hmm. Is that correct? It looks like a possible bug, because if both
    flags are true it will give invalid syntax like "FOR ALL TABLES FOR
    ALL SEQUENCES" instead of "FOR ALL TABLES, SEQUENCES"
    
    ======
    src/bin/pg_dump/t/002_pg_dump.pl
    
    12.
    This could also try the test scenario of both FOR ALL being
    simultaneously set ("FOR ALL TABLES, SEQUENCES") to check for bugs
    like the suspected one in dump.c review comment #11 above.
    
    ======
    src/bin/psql/describe.c
    
    13.
    + if (pset.sversion >= 170000)
    + printfPQExpBuffer(&buf,
    +   "SELECT pubname AS \"%s\",\n"
    +   "  pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
    +   "  puballtables AS \"%s\",\n"
    +   "  puballsequences AS \"%s\",\n"
    +   "  pubinsert AS \"%s\",\n"
    +   "  pubupdate AS \"%s\",\n"
    +   "  pubdelete AS \"%s\"",
    +   gettext_noop("Name"),
    +   gettext_noop("Owner"),
    +   gettext_noop("All tables"),
    +   gettext_noop("All sequences"),
    +   gettext_noop("Inserts"),
    +   gettext_noop("Updates"),
    +   gettext_noop("Deletes"));
    + else
    + printfPQExpBuffer(&buf,
    +   "SELECT pubname AS \"%s\",\n"
    +   "  pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
    +   "  puballtables AS \"%s\",\n"
    +   "  pubinsert AS \"%s\",\n"
    +   "  pubupdate AS \"%s\",\n"
    +   "  pubdelete AS \"%s\"",
    +   gettext_noop("Name"),
    +   gettext_noop("Owner"),
    +   gettext_noop("All tables"),
    +   gettext_noop("Inserts"),
    +   gettext_noop("Updates"),
    +   gettext_noop("Deletes"));
    +
    
    IMO this should be coded differently so that only the
    "puballsequences" column is guarded by the (pset.sversion >= 170000),
    and everything else is the same as before. This suggested way would
    also be consistent with the existing code version checks (e.g. for
    "pubtruncate" or for "pubviaroot").
    
    ~~~
    
    NITPICK - Add blank lines
    NITPICK - space in "ncols ++"
    
    ======
    src/bin/psql/tab-complete.c
    
    14.
    Hmm. When I tried this, it didn't seem to be working properly.
    
    For example "CREATE PUBLICATION pub1 FOR ALL" only completes with
    "TABLES" but not "SEQUENCES".
    For example "CREATE PUBLICATION pub1 FOR ALL SEQ" doesn't complete
    "SEQUENCES" properly
    
    ======
    src/include/catalog/pg_publication.h
    
    NITPICK - move the extern to be adjacent to others like it.
    
    ======
    src/include/nodes/parsenodes.h
    
    15.
    - bool for_all_tables; /* Special publication for all tables in db */
    + List    *for_all_objects; /* Special publication for all objects in
    + * db */
     } CreatePublicationStmt;
    
    I felt this List logic is a bit strange. See my comment #10 in gram.y
    for more details.
    
    ~~~
    
    16.
    - bool for_all_tables; /* Special publication for all tables in db */
    + List    *for_all_objects; /* Special publication for all objects in
    + * db */
    
    Ditto comment #15 in AlterPublicationStmt
    
    ======
    src/test/regress/sql/publication.sql
    
    17.
    +CREATE SEQUENCE testpub_seq0;
    +CREATE SEQUENCE pub_test.testpub_seq1;
    +
    +SET client_min_messages = 'ERROR';
    +CREATE PUBLICATION testpub_forallsequences FOR ALL SEQUENCES;
    +RESET client_min_messages;
    +
    +SELECT pubname, puballtables, puballsequences FROM pg_publication
    WHERE pubname = 'testpub_forallsequences';
    +\d+ pub_test.testpub_seq1
    
    Should you also do "\d+ tespub_seq0" here? Otherwise what was the
    point of defining the seq0 sequence being in this test?
    
    ~~~
    
    18.
    Maybe there are missing test cases for different syntax combinations like:
    
    FOR ALL TABLES, SEQUENCES
    FOR ALL SEQUENCES, TABLES
    
    Note that the current list logic of this patch even considers my
    following bogus statement syntax is OK.
    
    test_pub=# CREATE PUBLICATION pub_silly FOR ALL TABLES, SEQUENCES,
    TABLES, TABLES, TABLES, SEQUENCES;
    CREATE PUBLICATION
    test_pub=#
    
    ======
    99.
    Please also refer to the attached nitpicks patch which implements all
    the cosmetic issues identified above as NITPICKS.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  60. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-02T09:39:59Z

    On Wed, 26 Jun 2024 at 14:41, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Here are my initial review comments for the first patch v20240625-0001.
    >
    > ======
    > General
    >
    > 6.
    > I saw that RelationNeedsWAL() is called 2 times. It may make no sense,
    > but is it possible to assign that to a variable 1st time so you don't
    > need to call it 2nd time within the critical section?
    >
    
    I felt this is ok, we do similarly in other places also like
    fill_seq_fork_with_data function in the same file.
    
    I have fixed the other comments and merged the nitpicks changes. The
    attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  61. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-03T02:54:18Z

    Here are my comments for patch v20240702-0001
    
    They are all cosmetic and/or typos. Apart from these the 0001 patch LGTM.
    
    ======
    doc/src/sgml/func.sgml
    
    Section 9.17. Sequence Manipulation Functions
    
    pg_sequence_state:
    nitpick - typo /whethere/whether/
    nitpick - reworded slightly using a ChatGPT suggestion. (YMMV, so it
    is fine also if you prefer the current wording)
    
    ======
    src/backend/commands/sequence.c
    
    SetSequenceLastValue:
    nitpick - typo in function comment /diffrent/different/
    
    pg_sequence_state:
    nitpick - function comment wording: /page LSN/the page LSN/
    nitpick - moved some comment details about 'lsn_ret' into the function header
    nitpick - rearranged variable assignments to have consistent order
    with the values
    nitpick - tweaked comments
    nitpick - typo /whethere/whether/
    
    ======
    99.
    Please see the attached diffs patch which implements all those
    nitpicks mentioned above.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  62. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-03T14:39:24Z

    On Mon, 1 Jul 2024 at 12:57, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Here are some review comments for the patch v20240625-0002
    >
    > ======
    > Commit Message
    >
    > 1.
    > This commit enhances logical replication by enabling the inclusion of all
    > sequences in publications. This improvement facilitates seamless
    > synchronization of sequence data during operations such as
    > CREATE SUBSCRIPTION, REFRESH PUBLICATION, and REFRESH PUBLICATION SEQUENCES.
    >
    > ~
    >
    > Isn't this description getting ahead of the functionality a bit? For
    > example, it talks about operations like REFRESH PUBLICATION SEQUENCES
    > but AFAIK that syntax does not exist just yet.
    >
    > ~~~
    >
    > 2.
    > The commit message should mention that you are only introducing new
    > syntax for "FOR ALL SEQUENCES" here, but syntax for "FOR SEQUENCE" is
    > being deferred to some later patch. Without such a note it is not
    > clear why the gram.y syntax and docs seemed only half done.
    >
    > ======
    > doc/src/sgml/ref/create_publication.sgml
    >
    > 3.
    >     <varlistentry id="sql-createpublication-params-for-all-tables">
    >      <term><literal>FOR ALL TABLES</literal></term>
    > +    <term><literal>FOR ALL SEQUENCES</literal></term>
    >      <listitem>
    >       <para>
    > -      Marks the publication as one that replicates changes for all tables in
    > -      the database, including tables created in the future.
    > +      Marks the publication as one that replicates changes for all tables or
    > +      sequences in the database, including tables created in the future.
    >
    > It might be better here to keep descriptions for "ALL TABLES" and "ALL
    > SEQUENCES" separated, otherwise the wording does not quite seem
    > appropriate for sequences (e.g. where it says "including tables
    > created in the future").
    >
    > ~~~
    >
    > NITPICK - missing spaces
    > NITPICK - removed Oxford commas since previously there were none
    >
    > ~~~
    >
    > 4.
    > +   If <literal>FOR TABLE</literal>, <literal>FOR ALL TABLES</literal>,
    > +   <literal>FOR ALL SEQUENCES</literal>,or <literal>FOR TABLES IN
    > SCHEMA</literal>
    > +   are not specified, then the publication starts out with an empty set of
    > +   tables.  That is useful if tables or schemas are to be added later.
    >
    > It seems like "FOR ALL SEQUENCES" is out of place since it is jammed
    > between other clauses referring to TABLES. Would it be better to
    > mention SEQUENCES last in the list?
    >
    > ~~~
    >
    > 5.
    > +   rights on the table.  The <command>FOR ALL TABLES</command>,
    > +   <command>FOR ALL SEQUENCES</command>, and
    >     <command>FOR TABLES IN SCHEMA</command> clauses require the invoking
    >
    > ditto of #4 above.
    >
    > ======
    > src/backend/catalog/pg_publication.c
    >
    > GetAllSequencesPublicationRelations:
    >
    > NITPICK - typo /relation/relations/
    >
    > ======
    > src/backend/commands/publicationcmds.c
    >
    > 6.
    > + foreach(lc, stmt->for_all_objects)
    > + {
    > + char    *val = strVal(lfirst(lc));
    > +
    > + if (strcmp(val, "tables") == 0)
    > + for_all_tables = true;
    > + else if (strcmp(val, "sequences") == 0)
    > + for_all_sequences = true;
    > + }
    >
    > Consider the foreach_ptr macro to slightly simplify this code.
    > Actually, this whole logic seems cumbersome -- can’t the parser assign
    > flags automatically. Please see my more detailed comment #10 below
    > about this in gram.y
    >
    > ~~~
    >
    > 7.
    >   /* FOR ALL TABLES requires superuser */
    > - if (stmt->for_all_tables && !superuser())
    > + if (for_all_tables && !superuser())
    >   ereport(ERROR,
    >   (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    >   errmsg("must be superuser to create FOR ALL TABLES publication")));
    >
    > + /* FOR ALL SEQUENCES requires superuser */
    > + if (for_all_sequences && !superuser())
    > + ereport(ERROR,
    > + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    > + errmsg("must be superuser to create FOR ALL SEQUENCES publication")));
    > +
    >
    > The current code is easy to read, but I wonder if it should try harder
    > to share common code, or at least a common translatable message like
    > "must be superuser to create %s publication".
    >
    > ~~~
    >
    > 8.
    > - else
    > +
    > + /*
    > + * If the publication might have either tables or sequences (directly or
    > + * through a schema), process that.
    > + */
    > + if (!for_all_tables || !for_all_sequences)
    >
    > I did not understand why this code cannot just say "else" like before,
    > because the direct or through-schema syntax cannot be specified at the
    > same time as "FOR ALL ...", so why is the more complicated condition
    > necessary? Also, the similar code in AlterPublicationOptions() was not
    > changed to be like this.
    >
    > ======
    > src/backend/parser/gram.y
    >
    > 9. comment
    >
    >   *
    >   * CREATE PUBLICATION FOR ALL TABLES [WITH options]
    >   *
    > + * CREATE PUBLICATION FOR ALL SEQUENCES [WITH options]
    > + *
    >   * CREATE PUBLICATION FOR pub_obj [, ...] [WITH options]
    >
    > The comment is not quite correct because actually you are allowing
    > simultaneous FOR ALL TABLES, SEQUENCES. It should be more like:
    >
    > CREATE PUBLICATION FOR ALL pub_obj_type [,...] [WITH options]
    >
    > pub_obj_type is one of:
    > TABLES
    > SEQUENCES
    >
    > ~~~
    >
    > 10.
    > +pub_obj_type: TABLES
    > + { $$ = (Node *) makeString("tables"); }
    > + | SEQUENCES
    > + { $$ = (Node *) makeString("sequences"); }
    > + ;
    > +
    > +pub_obj_type_list: pub_obj_type
    > + { $$ = list_make1($1); }
    > + | pub_obj_type_list ',' pub_obj_type
    > + { $$ = lappend($1, $3); }
    > + ;
    >
    > IIUC the only thing you need is a flag to say if FOR ALL TABLE is in
    > effect and another flag to say if FOR ALL SEQUENCES is in effect. So,
    > It seemed clunky to build up a temporary list of "tables" or
    > "sequences" strings here, which is subsequently scanned by
    > CreatePublication to be turned back into booleans.
    >
    > Can't we just change the CreatePublicationStmt field to have:
    >
    > A) a 'for_all_types' bitmask instead of a list:
    > 0x0000 means FOR ALL is not specified
    > 0x0001 means ALL TABLES
    > 0x0010 means ALL SEQUENCES
    >
    > Or, B) have 2 boolean fields ('for_all_tables' and 'for_all_sequences')
    >
    > ...where the gram.y code can be written to assign the flag/s values directly?
    >
    > ======
    > src/bin/pg_dump/pg_dump.c
    >
    > 11.
    >   if (pubinfo->puballtables)
    >   appendPQExpBufferStr(query, " FOR ALL TABLES");
    >
    > + if (pubinfo->puballsequences)
    > + appendPQExpBufferStr(query, " FOR ALL SEQUENCES");
    > +
    >
    > Hmm. Is that correct? It looks like a possible bug, because if both
    > flags are true it will give invalid syntax like "FOR ALL TABLES FOR
    > ALL SEQUENCES" instead of "FOR ALL TABLES, SEQUENCES"
    >
    > ======
    > src/bin/pg_dump/t/002_pg_dump.pl
    >
    > 12.
    > This could also try the test scenario of both FOR ALL being
    > simultaneously set ("FOR ALL TABLES, SEQUENCES") to check for bugs
    > like the suspected one in dump.c review comment #11 above.
    >
    > ======
    > src/bin/psql/describe.c
    >
    > 13.
    > + if (pset.sversion >= 170000)
    > + printfPQExpBuffer(&buf,
    > +   "SELECT pubname AS \"%s\",\n"
    > +   "  pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
    > +   "  puballtables AS \"%s\",\n"
    > +   "  puballsequences AS \"%s\",\n"
    > +   "  pubinsert AS \"%s\",\n"
    > +   "  pubupdate AS \"%s\",\n"
    > +   "  pubdelete AS \"%s\"",
    > +   gettext_noop("Name"),
    > +   gettext_noop("Owner"),
    > +   gettext_noop("All tables"),
    > +   gettext_noop("All sequences"),
    > +   gettext_noop("Inserts"),
    > +   gettext_noop("Updates"),
    > +   gettext_noop("Deletes"));
    > + else
    > + printfPQExpBuffer(&buf,
    > +   "SELECT pubname AS \"%s\",\n"
    > +   "  pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
    > +   "  puballtables AS \"%s\",\n"
    > +   "  pubinsert AS \"%s\",\n"
    > +   "  pubupdate AS \"%s\",\n"
    > +   "  pubdelete AS \"%s\"",
    > +   gettext_noop("Name"),
    > +   gettext_noop("Owner"),
    > +   gettext_noop("All tables"),
    > +   gettext_noop("Inserts"),
    > +   gettext_noop("Updates"),
    > +   gettext_noop("Deletes"));
    > +
    >
    > IMO this should be coded differently so that only the
    > "puballsequences" column is guarded by the (pset.sversion >= 170000),
    > and everything else is the same as before. This suggested way would
    > also be consistent with the existing code version checks (e.g. for
    > "pubtruncate" or for "pubviaroot").
    >
    > ~~~
    >
    > NITPICK - Add blank lines
    > NITPICK - space in "ncols ++"
    >
    > ======
    > src/bin/psql/tab-complete.c
    >
    > 14.
    > Hmm. When I tried this, it didn't seem to be working properly.
    >
    > For example "CREATE PUBLICATION pub1 FOR ALL" only completes with
    > "TABLES" but not "SEQUENCES".
    > For example "CREATE PUBLICATION pub1 FOR ALL SEQ" doesn't complete
    > "SEQUENCES" properly
    >
    > ======
    > src/include/catalog/pg_publication.h
    >
    > NITPICK - move the extern to be adjacent to others like it.
    >
    > ======
    > src/include/nodes/parsenodes.h
    >
    > 15.
    > - bool for_all_tables; /* Special publication for all tables in db */
    > + List    *for_all_objects; /* Special publication for all objects in
    > + * db */
    >  } CreatePublicationStmt;
    >
    > I felt this List logic is a bit strange. See my comment #10 in gram.y
    > for more details.
    >
    > ~~~
    >
    > 16.
    > - bool for_all_tables; /* Special publication for all tables in db */
    > + List    *for_all_objects; /* Special publication for all objects in
    > + * db */
    >
    > Ditto comment #15 in AlterPublicationStmt
    >
    > ======
    > src/test/regress/sql/publication.sql
    >
    > 17.
    > +CREATE SEQUENCE testpub_seq0;
    > +CREATE SEQUENCE pub_test.testpub_seq1;
    > +
    > +SET client_min_messages = 'ERROR';
    > +CREATE PUBLICATION testpub_forallsequences FOR ALL SEQUENCES;
    > +RESET client_min_messages;
    > +
    > +SELECT pubname, puballtables, puballsequences FROM pg_publication
    > WHERE pubname = 'testpub_forallsequences';
    > +\d+ pub_test.testpub_seq1
    >
    > Should you also do "\d+ tespub_seq0" here? Otherwise what was the
    > point of defining the seq0 sequence being in this test?
    >
    > ~~~
    >
    > 18.
    > Maybe there are missing test cases for different syntax combinations like:
    >
    > FOR ALL TABLES, SEQUENCES
    > FOR ALL SEQUENCES, TABLES
    >
    > Note that the current list logic of this patch even considers my
    > following bogus statement syntax is OK.
    >
    > test_pub=# CREATE PUBLICATION pub_silly FOR ALL TABLES, SEQUENCES,
    > TABLES, TABLES, TABLES, SEQUENCES;
    > CREATE PUBLICATION
    > test_pub=#
    >
    > ======
    > 99.
    > Please also refer to the attached nitpicks patch which implements all
    > the cosmetic issues identified above as NITPICKS.
    
    Thank you for your feedback. I have addressed all the comments in the
    attached patch.
    
    Regards,
    Vignesh
    
  63. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-03T14:40:55Z

    On Wed, 3 Jul 2024 at 08:24, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Here are my comments for patch v20240702-0001
    >
    > They are all cosmetic and/or typos. Apart from these the 0001 patch LGTM.
    >
    > ======
    > doc/src/sgml/func.sgml
    >
    > Section 9.17. Sequence Manipulation Functions
    >
    > pg_sequence_state:
    > nitpick - typo /whethere/whether/
    > nitpick - reworded slightly using a ChatGPT suggestion. (YMMV, so it
    > is fine also if you prefer the current wording)
    >
    > ======
    > src/backend/commands/sequence.c
    >
    > SetSequenceLastValue:
    > nitpick - typo in function comment /diffrent/different/
    >
    > pg_sequence_state:
    > nitpick - function comment wording: /page LSN/the page LSN/
    > nitpick - moved some comment details about 'lsn_ret' into the function header
    > nitpick - rearranged variable assignments to have consistent order
    > with the values
    > nitpick - tweaked comments
    > nitpick - typo /whethere/whether/
    >
    > ======
    > 99.
    > Please see the attached diffs patch which implements all those
    > nitpicks mentioned above.
    
    Thank you for your feedback. I have addressed all the comments in the
    v20240703 version patch attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm0mSSrvHNRnC67f0HWMpoLW9UzxGVXimhwbRtKjE7Aa-Q%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  64. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-04T01:09:42Z

    Hi Vignesh. Here are my comments for the latest patch v20240703-0001.
    
    ======
    doc/src/sgml/func.sgml
    
    nitpick - /lsn/LSN/ (all other doc pages I found use uppercase for this acronym)
    
    ======
    src/backend/commands/sequence.c
    
    nitpick - /lsn/LSN/
    
    ======
    Please see attached nitpicks diff.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  65. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-04T03:35:20Z

    On Thu, 4 Jul 2024 at 06:40, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh. Here are my comments for the latest patch v20240703-0001.
    >
    > ======
    > doc/src/sgml/func.sgml
    >
    > nitpick - /lsn/LSN/ (all other doc pages I found use uppercase for this acronym)
    >
    > ======
    > src/backend/commands/sequence.c
    >
    > nitpick - /lsn/LSN/
    
    Thanks for the comments, the attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  66. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-04T07:13:54Z

    Here are my review comments for the patch v20240703-0002
    
    ======
    doc/src/sgml/ref/create_publication.sgml
    
    nitpick - consider putting the "FOR ALL SEQUENCES" para last, because
    eventually when more sequence syntax is added IMO it will be better to
    describe all the TABLES together, and then describe all the SEQUENCES
    together.
    
    nitpick - /synchronizing changes/synchronizes changes/
    
    Question: Was there a reason you chose wording "synchronizes changes"
    instead of having same "replicates changes" wording of FOR ALL TABLES?
    
    ======
    src/backend/catalog/system_views.sql
    
    1.
    Should there be some new test for the view? Otherwise, AFAICT this
    patch has no tests that will exercise the new function
    pg_get_publication_sequences.
    
    ======
    src/backend/commands/publicationcmds.c
    
    2.
    + errmsg("must be superuser to create FOR ALL %s publication",
    + stmt->for_all_tables ? "TABLES" : "SEQUENCES")));
    
    nitpick - the combined error message may be fine, but I think
    translators will prefer the substitution to be the full "FOR ALL
    TABLES" and "FOR ALL SEQUENCES" instead of just the keywords that are
    different.
    
    ======
    src/backend/parser/gram.y
    
    3.
    Some of these new things maybe could be named better?
    
    'preprocess_allpubobjtype_list' => 'preprocess_pub_all_objtype_list'
    
    'AllPublicationObjSpec *allpublicationobjectspec;' =>
    'PublicationAllObjSpec *publicationallobjectspec;'
    
    (I didn't include these in nitpicks diffs because you probably have
    better ideas than I do for good names)
    
    ~~~
    
    nitpick - typo in comment /SCHEMAS/SEQUENCES/
    
    preprocess_allpubobjtype_list:
    nitpick - typo /allbjects_list/all_objects_list/
    nitpick - simplify /allpubob/obj/
    nitpick - add underscores in the enums
    
    ======
    src/bin/pg_dump/pg_dump.c
    
    4.
    + if (pubinfo->puballtables || pubinfo->puballsequences)
    + {
    + appendPQExpBufferStr(query, " FOR ALL");
    + if (pubinfo->puballtables &&  pubinfo->puballsequences)
    + appendPQExpBufferStr(query, " TABLES, SEQUENCES");
    + else if (pubinfo->puballtables)
    + appendPQExpBufferStr(query, " TABLES");
    + else
    + appendPQExpBufferStr(query, " SEQUENCES");
    + }
    
    nitpick - it seems over-complicated; See nitpicks diff for my suggestion.
    
    ======
    src/include/nodes/parsenodes.h
    
    nitpick - put underscores in the enum values
    
    ~~
    
    5.
    - bool for_all_tables; /* Special publication for all tables in db */
    + List    *for_all_objects; /* Special publication for all objects in
    + * db */
    
    Is this OK? Saying "for all objects" seemed misleading.
    
    ======
    src/test/regress/sql/publication.sql
    
    nitpick - some small changes to comments, e.g. writing keywords in uppercase
    
    ~~~
    
    6.
    I asked this before in a previous review [1-#17] -- I didn't
    understand the point of the sequence 'testpub_seq0' since nobody seems
    to be doing anything with it. Should it just be removed? Or is there a
    missing test case to use it?
    
    ~~~
    
    7.
    Other things to consider:
    
    (I didn't include these in my attached diff)
    
    * could use a single CREATE SEQUENCE stmt instead of multiple
    
    * could use a single DROP PUBLICATION stmt instead of multiple
    
    * shouldn't all publication names ideally have a 'regress_' prefix?
    
    ======
    99.
    Please refer to the attached nitpicks diff which has implementation
    for the nitpicks cited above.
    
    ======
    [1] https://www.postgresql.org/message-id/CAHut%2BPvrk75vSDkaXJVmhhZuuqQSY98btWJV%3DBMZAnyTtKRB4g%40mail.gmail.com
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  67. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-04T07:44:30Z

    The latest (v20240704) patch 0001 LGTM
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  68. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-05T04:15:36Z

    Hi Vignesh.
    
    After applying the v20240703-0003 patch, I was always getting errors
    when running the subscription TAP tests.
    
    # +++ tap check in src/test/subscription +++
    t/001_rep_changes.pl ............... ok
    t/002_types.pl ..................... ok
    t/003_constraints.pl ............... ok
    t/004_sync.pl ...................... ok
    t/005_encoding.pl .................. ok
    t/006_rewrite.pl ................... ok
    t/007_ddl.pl ....................... 3/?
    #   Failed test 'Alter subscription set publication throws warning for
    non-existent publication'
    #   at t/007_ddl.pl line 67.
    Bailout called.  Further testing stopped:  pg_ctl stop failed
    # Tests were run but no plan was declared and done_testing() was not seen.
    FAILED--Further testing stopped: pg_ctl stop failed
    make: *** [check] Error 255
    
    ~~~
    
    The publisher log shows an Assert TRAP occurred:
    
    2024-07-04 18:15:40.089 AEST [745] mysub1 LOG:  statement: SELECT
    DISTINCT s.schemaname, s.sequencename
      FROM pg_catalog.pg_publication_sequences s
    WHERE s.pubname IN ('mypub', 'non_existent_pub', 'non_existent_pub1',
    'non_existent_pub2')
    TRAP: failed Assert("IsA(list, OidList)"), File:
    "../../../src/include/nodes/pg_list.h", Line: 323, PID: 745
    
    ~~~
    
    A debugging backtrace looks like below:
    
    Core was generated by `postgres: publisher: walsender postgres
    postgres [local] SELECT               '.
    Program terminated with signal 6, Aborted.
    #0  0x00007f36f44f02c7 in raise () from /lib64/libc.so.6
    Missing separate debuginfos, use: debuginfo-install
    glibc-2.17-260.el7_6.6.x86_64 pcre-8.32-17.el7.x86_64
    (gdb) bt
    #0  0x00007f36f44f02c7 in raise () from /lib64/libc.so.6
    #1  0x00007f36f44f19b8 in abort () from /lib64/libc.so.6
    #2  0x0000000000bb8be1 in ExceptionalCondition (conditionName=0xc7aa6c
    "IsA(list, OidList)",
        fileName=0xc7aa10 "../../../src/include/nodes/pg_list.h",
    lineNumber=323) at assert.c:66
    #3  0x00000000005f2c57 in list_nth_oid (list=0x27948f0, n=0) at
    ../../../src/include/nodes/pg_list.h:323
    #4  0x00000000005f5491 in pg_get_publication_sequences
    (fcinfo=0x2796a00) at pg_publication.c:1334
    #5  0x0000000000763d10 in ExecMakeTableFunctionResult
    (setexpr=0x27b2fd8, econtext=0x27b2ef8, argContext=0x2796900,
    ...
    
    Something goes wrong indexing into that 'sequences' list.
    
    1329 funcctx = SRF_PERCALL_SETUP();
    1330 sequences = (List *) funcctx->user_fctx;
    1331
    1332 if (funcctx->call_cntr < list_length(sequences))
    1333 {
    1334 Oid relid = list_nth_oid(sequences, funcctx->call_cntr);
    1335
    1336 SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(relid));
    1337 }
    
    ======
    
    Perhaps now it is time to create a CF entry for this thread because
    the cfbot could have detected the error earlier.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  69. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-05T11:58:26Z

    On Thu, 4 Jul 2024 at 12:44, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Here are my review comments for the patch v20240703-0002
    >
    > ======
    > doc/src/sgml/ref/create_publication.sgml
    >
    >
    > Question: Was there a reason you chose wording "synchronizes changes"
    > instead of having same "replicates changes" wording of FOR ALL TABLES?
    
    Since at this point we are only supporting sync of sequences, there
    are no incremental changes being replicated to subscribers. I thought
    synchronization is better suited here.
    
    > ======
    > src/backend/catalog/system_views.sql
    >
    > 1.
    > Should there be some new test for the view? Otherwise, AFAICT this
    > patch has no tests that will exercise the new function
    > pg_get_publication_sequences.
    
    pg_publication_sequences view uses pg_get_publication_sequences which
    will be tested with 3rd patch while creating subscription/refreshing
    publication sequences. I felt it is ok not to have a test here.
    
    > 5.
    > - bool for_all_tables; /* Special publication for all tables in db */
    > + List    *for_all_objects; /* Special publication for all objects in
    > + * db */
    >
    > Is this OK? Saying "for all objects" seemed misleading.
    
    This change is not required, reverting it.
    
    > 6.
    > I asked this before in a previous review [1-#17] -- I didn't
    > understand the point of the sequence 'testpub_seq0' since nobody seems
    > to be doing anything with it. Should it just be removed? Or is there a
    > missing test case to use it?
    
    Since we are having all sequences published I wanted to have a
    sequence in another schema also. Adding describe for it too.
    
    > ~~~
    >
    > 7.
    > Other things to consider:
    >
    > (I didn't include these in my attached diff)
    >
    > * could use a single CREATE SEQUENCE stmt instead of multiple
    
    CREATE SEQUENCE does not support specifying multiple sequences in one
    statement, skipping this.
    
    The rest of the comments are fixed, the attached v20240705 version
    patch has the changes for the same.
    
    Regards,
    Vignesh
    
  70. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-05T12:05:34Z

    On Fri, 5 Jul 2024 at 09:46, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh.
    >
    > After applying the v20240703-0003 patch, I was always getting errors
    > when running the subscription TAP tests.
    >
    > # +++ tap check in src/test/subscription +++
    > t/001_rep_changes.pl ............... ok
    > t/002_types.pl ..................... ok
    > t/003_constraints.pl ............... ok
    > t/004_sync.pl ...................... ok
    > t/005_encoding.pl .................. ok
    > t/006_rewrite.pl ................... ok
    > t/007_ddl.pl ....................... 3/?
    > #   Failed test 'Alter subscription set publication throws warning for
    > non-existent publication'
    > #   at t/007_ddl.pl line 67.
    > Bailout called.  Further testing stopped:  pg_ctl stop failed
    > # Tests were run but no plan was declared and done_testing() was not seen.
    > FAILED--Further testing stopped: pg_ctl stop failed
    > make: *** [check] Error 255
    >
    > ~~~
    >
    > The publisher log shows an Assert TRAP occurred:
    >
    > 2024-07-04 18:15:40.089 AEST [745] mysub1 LOG:  statement: SELECT
    > DISTINCT s.schemaname, s.sequencename
    >   FROM pg_catalog.pg_publication_sequences s
    > WHERE s.pubname IN ('mypub', 'non_existent_pub', 'non_existent_pub1',
    > 'non_existent_pub2')
    > TRAP: failed Assert("IsA(list, OidList)"), File:
    > "../../../src/include/nodes/pg_list.h", Line: 323, PID: 745
    >
    > ~~~
    >
    > A debugging backtrace looks like below:
    >
    > Core was generated by `postgres: publisher: walsender postgres
    > postgres [local] SELECT               '.
    > Program terminated with signal 6, Aborted.
    > #0  0x00007f36f44f02c7 in raise () from /lib64/libc.so.6
    > Missing separate debuginfos, use: debuginfo-install
    > glibc-2.17-260.el7_6.6.x86_64 pcre-8.32-17.el7.x86_64
    > (gdb) bt
    > #0  0x00007f36f44f02c7 in raise () from /lib64/libc.so.6
    > #1  0x00007f36f44f19b8 in abort () from /lib64/libc.so.6
    > #2  0x0000000000bb8be1 in ExceptionalCondition (conditionName=0xc7aa6c
    > "IsA(list, OidList)",
    >     fileName=0xc7aa10 "../../../src/include/nodes/pg_list.h",
    > lineNumber=323) at assert.c:66
    > #3  0x00000000005f2c57 in list_nth_oid (list=0x27948f0, n=0) at
    > ../../../src/include/nodes/pg_list.h:323
    > #4  0x00000000005f5491 in pg_get_publication_sequences
    > (fcinfo=0x2796a00) at pg_publication.c:1334
    > #5  0x0000000000763d10 in ExecMakeTableFunctionResult
    > (setexpr=0x27b2fd8, econtext=0x27b2ef8, argContext=0x2796900,
    > ...
    >
    > Something goes wrong indexing into that 'sequences' list.
    >
    > 1329 funcctx = SRF_PERCALL_SETUP();
    > 1330 sequences = (List *) funcctx->user_fctx;
    > 1331
    > 1332 if (funcctx->call_cntr < list_length(sequences))
    > 1333 {
    > 1334 Oid relid = list_nth_oid(sequences, funcctx->call_cntr);
    > 1335
    > 1336 SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(relid));
    > 1337 }
    
    I was not able to reproduce this issue after several runs, but looks
    like sequences need to be initialized here.
    
    > Perhaps now it is time to create a CF entry for this thread because
    > the cfbot could have detected the error earlier.
    
    I have added a commitfest entry for the same at [1].
    
    The v20240705 version patch attached at [2] has the change for the same.
    
    [1] - https://commitfest.postgresql.org/49/5111/
    [2] - https://www.postgresql.org/message-id/CALDaNm3WvLUesGq54JagEkbBh4CBfMoT84Rw7HjL8KML_BSzPw%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  71. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-10T04:03:44Z

    On Fri, Jul 5, 2024 at 9:58 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 4 Jul 2024 at 12:44, Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > 1.
    > > Should there be some new test for the view? Otherwise, AFAICT this
    > > patch has no tests that will exercise the new function
    > > pg_get_publication_sequences.
    >
    > pg_publication_sequences view uses pg_get_publication_sequences which
    > will be tested with 3rd patch while creating subscription/refreshing
    > publication sequences. I felt it is ok not to have a test here.
    >
    
    OTOH, if there had been such a test here then the ("sequence = NIL")
    bug in patch 0002 code would have been caught earlier in patch 0002
    testing instead of later in patch 0003 testing. In general, I think
    each patch should be self-contained w.r.t. to testing all of its new
    code, but if you think another test here is overkill then I am fine
    with that too.
    
    //////////
    
    Meanwhile, here are my review comments for patch v20240705-0002
    
    ======
    doc/src/sgml/ref/create_publication.sgml
    
    1.
    The CREATE PUBLICATION page has many examples showing many different
    combinations of syntax. I think it would not hurt to add another one
    showing SEQUENCES being used.
    
    ======
    src/backend/commands/publicationcmds.c
    
    2.
    + if (form->puballsequences && !superuser_arg(newOwnerId))
    + ereport(ERROR,
    + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    + errmsg("permission denied to change owner of publication \"%s\"",
    + NameStr(form->pubname)),
    + errhint("The owner of a FOR ALL SEQUENCES publication must be a
    superuser.")));
    
    You might consider combining this with the previous error in the same
    way that the "FOR ALL TABLES" and "FOR ALL SEQUENCES" errors were
    combined in CreatePublication. The result would be less code. But, I
    also think your current code is fine, so I am just putting this out as
    an idea in case you prefer it.
    
    ======
    src/backend/parser/gram.y
    
    nitpick - added a space in the comment
    nitpick - changed the call order slightly because $6 comes before $7
    
    ======
    src/bin/pg_dump/pg_dump.c
    
    3. getPublications
    
    - if (fout->remoteVersion >= 130000)
    + if (fout->remoteVersion >= 170000)
    
    This should be 180000.
    
    ======
    src/bin/psql/describe.c
    
    4. describeOneTableDetails
    
    + /* print any publications */
    + if (pset.sversion >= 170000)
    + {
    
    This should be 180000.
    
    ~~~
    
    describeOneTableDetails:
    nitpick - removed a redundant "else"
    nitpick - simplified the "Publications:" header logic slightly
    
    ~~~
    
    5. listPublications
    
    + if (pset.sversion >= 170000)
    + appendPQExpBuffer(&buf,
    +   ",\n  puballsequences AS \"%s\"",
    +   gettext_noop("All sequences"));
    
    This should be 180000.
    
    ~~~
    
    6. describePublications
    
    + has_pubsequence = (pset.sversion >= 170000);
    
    This should be 180000.
    
    ~
    
    nitpick - remove some blank lines for consistency with nearby code
    
    ======
    src/include/nodes/parsenodes.h
    
    nitpick - minor change to comment for PublicationAllObjType
    nitpick - the meanings of the enums are self-evident; I didn't think
    comments were very useful
    
    ======
    src/test/regress/sql/publication.sql
    
    7.
    I think it will also be helpful to arrange for a SEQUENCE to be
    published by *multiple* publications. This would test that they get
    listed as expected in the "Publications:" part of the "describe" (\d+)
    for the sequence.
    
    ======
    99.
    Please also see the attached diffs patch which implements any nitpicks
    mentioned above.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  72. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-10T08:16:03Z

    Here are a few comments for patch v20240705-0003.
    
    (This is a WIP. I have only looked at the docs so far.)
    
    ======
    doc/src/sgml/config.sgml
    
    nitpick - max_logical_replication_workers: /and sequence
    synchornization worker/and a sequence synchornization worker/
    
    ======
    doc/src/sgml/logical-replication.sgml
    
    nitpick - max_logical_replication_workers: re-order list of workers to
    be consistent with other docs 1-apply,2-parallel,3-tablesync,4-seqsync
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    1.
    IIUC the existing "REFRESH PUBLICATION" command will fetch and sync
    all new sequences, etc., and/or remove old ones no longer in the
    publication. But current docs do not say anything at all about
    sequences here. It should say something about sequence behaviour.
    
    ~~~
    
    2.
    For the existing "REFRESH PUBLICATION" there is a sub-option
    "copy_data=true/false". Won't this need some explanation about how it
    behaves for sequences? Or will there be another option
    "copy_sequences=true/false".
    
    ~~~
    
    3.
    IIUC the main difference between REFRESH PUBLICATION and REFRESH
    PUBLICATION SEQUENCES is that the 2nd command will try synchronize
    with all the *existing* sequences to bring them to the same point as
    on the publisher, but otherwise, they are the same command. If that is
    correct understanding I don't think that distinction is made very
    clear in the current docs.
    
    ~~~
    
    nitpick - the synopsis is misplaced. It should not be between ENABLE
    and DISABLE. I moved it. Also, it should say "REFRESH PUBLICATION
    SEQUENCES" because that is how the new syntax is defined in gram.y
    
    nitpick - REFRESH SEQUENCES. Renamed to "REFRESH PUBLICATION
    SEQUENCES". And, shouldn't "from the publisher" say "with the
    publisher"?
    
    nitpick - changed the varlistentry "id".
    
    ======
    99.
    Please also see the attached diffs patch which implements any nitpicks
    mentioned above.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  73. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-12T02:52:25Z

    Hi Vignesh. Here are the rest of my comments for patch v20240705-0003.
    
    (Apologies for the length of this post; but it was unavoidable due to
    this being the 1st review of a very large large 1700-line patch)
    
    ======
    src/backend/catalog/pg_subscription.c
    
    1. GetSubscriptionSequences
    
    +/*
    + * Get the sequences for the subscription.
    + *
    + * The returned list is palloc'ed in the current memory context.
    + */
    
    Is that comment right? The palloc seems to be done in
    CacheMemoryContext, not in the current context.
    
    ~
    
    2.
    The code is very similar to the other function
    GetSubscriptionRelations(). In fact I did not understand how the 2
    functions know what they are returning:
    
    E.g. how does GetSubscriptionRelations not return sequences too?
    E.g. how does GetSubscriptionSequences not return relations too?
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    CreateSubscription:
    nitpick - put the sequence logic *after* the relations logic because
    that is the order that seems used everywhere else.
    
    ~~~
    
    3. AlterSubscription_refresh
    
    - logicalrep_worker_stop(sub->oid, relid);
    + /* Stop the worker if relation kind is not sequence*/
    + if (relkind != RELKIND_SEQUENCE)
    + logicalrep_worker_stop(sub->oid, relid);
    
    Can you give more reasons in the comment why skip the stop for sequence worker?
    
    ~
    
    nitpick - period and space in the comment
    
    ~~~
    
    4.
      for (off = 0; off < remove_rel_len; off++)
      {
      if (sub_remove_rels[off].state != SUBREL_STATE_READY &&
    - sub_remove_rels[off].state != SUBREL_STATE_SYNCDONE)
    + sub_remove_rels[off].state != SUBREL_STATE_SYNCDONE &&
    + get_rel_relkind(sub_remove_rels[off].relid) != RELKIND_SEQUENCE)
      {
    Would this new logic perhaps be better written as:
    
    if (get_rel_relkind(sub_remove_rels[off].relid) == RELKIND_SEQUENCE)
      continue;
    
    ~~~
    
    AlterSubscription_refreshsequences:
    nitpick - rename AlterSubscription_refresh_sequences
    
    ~
    5.
    There is significant code overlap between the existing
    AlterSubscription_refresh and the new function
    AlterSubscription_refreshsequences. I wonder if it is better to try to
    combine the logic and just pass another parameter to
    AlterSubscription_refresh saying to update the existing sequences if
    necessary. Particularly since the AlterSubscription_refresh is already
    tweaked to work for sequences. Of course, the resulting combined
    function would be large and complex, but maybe that would still be
    better than having giant slabs of nearly identical cut/paste code.
    Thoughts?
    
    ~~~
    
    check_publications_origin:
    nitpick - move variable declarations
    ~~~
    
    fetch_sequence_list:
    nitpick - change /tablelist/seqlist/
    nitpick - tweak the spaces of the SQL for alignment (similar to
    fetch_table_list)
    
    ~
    
    6.
    +    " WHERE s.pubname IN (");
    + first = true;
    + foreach_ptr(String, pubname, publications)
    + {
    + if (first)
    + first = false;
    + else
    + appendStringInfoString(&cmd, ", ");
    +
    + appendStringInfoString(&cmd, quote_literal_cstr(pubname->sval));
    + }
    + appendStringInfoChar(&cmd, ')');
    
    IMO this can be written much better by using get_publications_str()
    function to do all this list work.
    
    ======
    src/backend/replication/logical/launcher.c
    
    7. logicalrep_worker_find
    
    /*
     * Walks the workers array and searches for one that matches given
     * subscription id and relid.
     *
     * We are only interested in the leader apply worker or table sync worker.
     */
    
    The above function comment (not in the patch 0003) is stale because
    this AFAICT this is also going to return sequence workers if it finds
    one.
    
    ~~~
    
    8. logicalrep_sequence_sync_worker_find
    
    +/*
    + * Walks the workers array and searches for one that matches given
    + * subscription id.
    + *
    + * We are only interested in the sequence sync worker.
    + */
    +LogicalRepWorker *
    +logicalrep_sequence_sync_worker_find(Oid subid, bool only_running)
    
    There are other similar functions for walking the workers array to
    search for a worker. Instead of having different functions for
    different cases, wouldn't it be cleaner to combine these into a single
    function, where you pass a parameter (e.g. a mask of worker types that
    you are interested in finding)?
    
    ~
    
    nitpick - declare a for loop variable 'i'
    
    ~~~
    
    9. logicalrep_apply_worker_find
    
    +static LogicalRepWorker *
    +logicalrep_apply_worker_find(Oid subid, bool only_running)
    
    All the other find* functions assume the lock is already held
    (Assert(LWLockHeldByMe(LogicalRepWorkerLock));). But this one is
    different. IMO it might be better to acquire the lock in the caller to
    make all the find* functions look the same. Anyway, that will help to
    combine everything into 1 "find" worker as suggested in the previous
    review comment #8.
    
    ~
    
    nitpick - declare a for loop variable 'i'
    nitpick - removed unnecessary parens in condition.
    
    ~~~
    
    10. logicalrep_worker_launch
    
    /*----------
    * Sanity checks:
    * - must be valid worker type
    * - tablesync workers are only ones to have relid
    * - parallel apply worker is the only kind of subworker
    */
    
    The above code-comment (not in the 0003 patch) seems stale. This
    should now also mention sequence sync workers, right?
    
    ~~~
    
    11.
    - Assert(is_tablesync_worker == OidIsValid(relid));
    + Assert(is_tablesync_worker == OidIsValid(relid) ||
    is_sequencesync_worker == OidIsValid(relid));
    
    IIUC there is only a single sequence sync worker for handling all the
    sequences. So, what does the 'relid' actually mean here when there are
    multiple sequences?
    
    ~~~
    
    12. logicalrep_seqsyncworker_failuretime
    
    +/*
    + * Set the sequence sync worker failure time
    + *
    + * Called on sequence sync worker failure exit.
    + */
    
    12a.
    The comment should be improved to make it more clear that the failure
    time of the sync worker information is stored with the *apply* worker.
    See also other review comments in this post about this area -- perhaps
    all this can be removed?
    
    ~
    
    12b.
    Curious if this had to be a separate exit handler or if may this could
    have been handled by the existing logicalrep_worker_onexit handler.
    See also other review comments int this post about this area --
    perhaps all this can be removed?
    
    ======
    .../replication/logical/sequencesync.c
    
    13. fetch_sequence_data
    
    13a.
    The function comment has no explanation of what exactly the returned
    value means. It seems like it is what you will assign as 'last_value'
    on the subscriber-side.
    
    ~
    
    13b.
    Some of the table functions like this are called like
    'fetch_remote_table_info()'. Maybe it is better to do similar here
    (e.g. include the word "remote" in the function name).
    
    ~
    
    14.
    The reason for the addition logic "(last_value + log_cnt)" is not
    obvious. I am guessing it might be related to code from
    'nextval_internal' (fetch = log = fetch + SEQ_LOG_VALS;) but it is
    complicated. It is unfortunate that the field 'log_cnt' seems hardly
    commented anywhere at all.
    
    Also, I am not 100% sure if I trust the logic in the first place. The
    caller of this function is doing:
    sequence_value = fetch_sequence_data(conn, remoteid, &lsn);
    /* sets the sequence with sequence_value */
    SetSequenceLastValue(RelationGetRelid(rel), sequence_value);
    
    Won't that mean you can get to a situation where subscriber-side
    result of lastval('s') can be *ahead* from lastval('s') on the
    publisher? That doesn't seem good.
    
    ~~~
    
    copy_sequence:
    
    nitpick - ERROR message. Reword "for table..." to be more like the 2nd
    error message immediately below.
    nitpick - /RelationGetRelationName(rel)/relname/
    nitpick - moved the Assert for 'relkind' to be nearer the assignment.
    
    ~
    
    15.
    + /*
    + * Logical replication of sequences is based on decoding WAL records,
    + * describing the "next" state of the sequence the current state in the
    + * relfilenode is yet to reach. But during the initial sync we read the
    + * current state, so we need to reconstruct the WAL record logged when we
    + * started the current batch of sequence values.
    + *
    + * Otherwise we might get duplicate values (on subscriber) if we failed
    + * over right after the sync.
    + */
    + sequence_value = fetch_sequence_data(conn, remoteid, &lsn);
    +
    + /* sets the sequence with sequence_value */
    + SetSequenceLastValue(RelationGetRelid(rel), sequence_value);
    
    (This is related to some earlier review comment #14 above). IMO all
    this tricky commentary belongs in the function header of
    "fetch_sequence_data", where it should be describing that function's
    return value.
    
    ~~~
    
    LogicalRepSyncSequences:
    nitpick - declare void param
    nitpick indentation
    nitpick - wrapping
    nitpick - /sequencerel/sequence_rel/
    nitpick - blank lines
    
    ~
    
    16.
    + if (check_enable_rls(RelationGetRelid(sequencerel), InvalidOid,
    false) == RLS_ENABLED)
    + ereport(ERROR,
    + errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    + errmsg("user \"%s\" cannot replicate into relation with row-level
    security enabled: \"%s\"",
    + GetUserNameFromId(GetUserId(), true),
    + RelationGetRelationName(sequencerel)));
    
    This should be reworded to refer to sequences instead of relations. Maybe like:
    user \"%s\" cannot replicate into sequence \"%s\" with row-level
    security enabled"
    
    ~
    
    17.
    The Calculations involving the BATCH size seem a bit tricky.
    e.g. in 1st place it is doing: (curr_seq % MAX_SEQUENCES_SYNC_PER_BATCH == 0)
    e.g. in 2nd place it is doing: (next_seq % MAX_SEQUENCES_SYNC_PER_BATCH) == 0)
    
    Maybe this batch logic can be simplified somehow using a bool variable
    for the calculation?
    
    Also, where does the number 100 come from? Why not 1000? Why not 10?
    Why have batching at all? Maybe there should be some comment to
    describe the reason and the chosen value.
    
    ~
    
    18.
    + next_seq = curr_seq + 1;
    + if (((next_seq % MAX_SEQUENCES_SYNC_PER_BATCH) == 0) || next_seq == seq_count)
    + {
    + /* LOG all the sequences synchronized during current batch. */
    + int i = curr_seq - (curr_seq % MAX_SEQUENCES_SYNC_PER_BATCH);
    + for (; i <= curr_seq; i++)
    + {
    + SubscriptionRelState *done_seq;
    + done_seq = (SubscriptionRelState *) lfirst(list_nth_cell(sequences, i));
    + ereport(LOG,
    + errmsg("logical replication synchronization for subscription \"%s\",
    sequence \"%s\" has finished",
    +    get_subscription_name(subid, false), get_rel_name(done_seq->relid)));
    + }
    +
    + CommitTransactionCommand();
    + }
    +
    + curr_seq++;
    
    I feel this batching logic needs more comments describing what you are
    doing here.
    
    ~~~
    
    SequencesyncWorkerMain:
    nitpick - spaces in the function comment
    
    ======
    src/backend/replication/logical/tablesync.c
    
    19. finish_sync_worker
    
    -finish_sync_worker(void)
    +finish_sync_worker(bool istable)
    
    IMO, for better readability (here and in the callers) the new
    parameter should be the enum LogicalRepWorkerType. Since we have that
    enum, might as well make good use of it.
    
    ~
    
    nitpick - /sequences synchronization worker/sequence synchronization worker/
    nitpick - comment tweak
    
    ~
    
    20.
    + char relkind;
    +
    + if (!started_tx)
    + {
    + StartTransactionCommand();
    + started_tx = true;
    + }
    +
    + relkind = get_rel_relkind(rstate->relid);
    + if (relkind == RELKIND_SEQUENCE)
    + continue;
    
    I am wondering is it possible to put the relkind check can come
    *before* the TX code here, because in case there are *only* sequences
    then maybe every would be skipped and there would have been no need
    for any TX at all in the first place.
    
    ~~~
    
    process_syncing_sequences_for_apply:
    
    nitpick - fix typo and slight reword function header comment. Also
    /last start time/last failure time/
    nitpick - tweak comments
    nitpick - blank lines
    
    ~
    
    21.
    + if (!started_tx)
    + {
    + StartTransactionCommand();
    + started_tx = true;
    + }
    +
    + relkind = get_rel_relkind(rstate->relid);
    + if (relkind != RELKIND_SEQUENCE || rstate->state != SUBREL_STATE_INIT)
    + continue;
    
    Wondering (like in review comment #20) if it is possible to swap those
    because maybe there was no reason for any TX if the other condition
    would always continue.
    
    ~~~
    
    22.
    + if (nsyncworkers < max_sync_workers_per_subscription)
    + {
    + TimestampTz now = GetCurrentTimestamp();
    + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    +    now, wal_retrieve_retry_interval))
    + {
    + MyLogicalRepWorker->sequencesync_failure_time = 0;
    
    It seems to me that storing 'sequencesync_failure_time' logic may be
    unnecessarily complicated. Can't the same "throttling" be achieved by
    storing the synchronization worker 'start time' instead of 'fail
    time', in which case then you won't have to mess around with
    considering if the sync worker failed or just exited normally etc? You
    might also be able to remove all the
    logicalrep_seqsyncworker_failuretime() exit handler code.
    
    ~~~
    
    process_syncing_tables:
    nitpick - let's process tables before sequences (because all other
    code is generally in this same order)
    nitpick - removed some excessive comments about code that is not
    supposed to happen
    
    ======
    src/backend/replication/logical/worker.c
    
    should_apply_changes_for_rel:
    nitpick - IMO there were excessive comments for something that is not
    going to happen
    
    ~~~
    
    23. InitializeLogRepWorker
    
    /*
     * Common initialization for leader apply worker, parallel apply worker and
     * tablesync worker.
     *
     * Initialize the database connection, in-memory subscription and necessary
     * config options.
     */
    
    That comment (not part of patch 0003) is stale; it should now mention
    the sequence sync worker as well, right?
    
    ~
    
    nitpick - Tweak plural /sequences sync worker/sequence sync worker/
    
    ~~~
    
    24. SetupApplyOrSyncWorker
    
    /* Common function to setup the leader apply or tablesync worker. */
    
    That comment (not part of patch 0003) is stale; it should now mention
    the sequence sync worker as well, right?
    
    ======
    src/include/nodes/parsenodes.h
    
    25.
      ALTER_SUBSCRIPTION_ADD_PUBLICATION,
      ALTER_SUBSCRIPTION_DROP_PUBLICATION,
      ALTER_SUBSCRIPTION_REFRESH,
    + ALTER_SUBSCRIPTION_REFRESH_PUBLICATION_SEQUENCES,
    
    For consistency with your new enum it would be better to also change
    the existing enum name ALTER_SUBSCRIPTION_REFRESH ==>
    ALTER_SUBSCRIPTION_REFRESH_PUBLICATION.
    
    ======
    src/include/replication/logicalworker.h
    
    nitpick - IMO should change the function name
    /SequencesyncWorkerMain/SequenceSyncWorkerMain/, and in passing make
    the same improvement to the TablesyncWorkerMain function name.
    
    ======
    src/include/replication/worker_internal.h
    
    26.
      WORKERTYPE_PARALLEL_APPLY,
    + WORKERTYPE_SEQUENCESYNC,
     } LogicalRepWorkerType;
    
    AFAIK the enum order should not matter here so it would be better to
    put the WORKERTYPE_SEQUENCESYNC directly after the
    WORKERTYPE_TABLESYNC to keep the similar things together.
    
    ~
    
    nitpick - IMO change the macro name
    /isSequencesyncWorker/isSequenceSyncWorker/, and in passing make the
    same improvement to the isTablesyncWorker macro name.
    
    ======
    src/test/subscription/t/034_sequences.pl
    
    nitpick - Copyright year
    nitpick - Modify the "Create subscriber node" comment for consistency
    nitpick - Modify comments slightly for the setup structure parts
    nitpick - Add or remove various blank lines
    nitpick - Since you have sequences 's2' and 's3', IMO it makes more
    sense to call the original sequence 's1' instead of just 's'
    nitpick - Rearrange so the CREATE PUBLICATION/SUBSCRIPTION can stay together
    nitpick - Modified some comment styles to clearly delineate all the
    main "TEST" scenarios
    nitpick - In the REFRESH PUBLICATION test the create new sequence and
    update existing can be combined (like you do in a later test).
    nitpick - Changed some of the test messages for REFRESH PUBLICATION
    which seemed wrong
    nitpick - Added another test for 's1' in REFRESH PUBLICATION SEQUENCES
    nitpick - Changed some of the test messages for REFRESH PUBLICATION
    SEQUENCES which seemed wrong
    
    ~
    
    27.
    IIUC the preferred practice is to give these test object names a
    'regress_' prefix.
    
    ~
    
    28.
    +# Check the data on subscriber
    +$result = $node_subscriber->safe_psql(
    + 'postgres', qq(
    + SELECT * FROM s;
    +));
    +
    +is($result, '132|0|t', 'initial test data replicated');
    
    28a.
    Maybe it is better to say "SELECT last_value, log_cnt, is_called"
    instead of "SELECT *" ?
    Note - this is in a couple of places.
    
    ~
    
    28b.
    Can you explain why the expected sequence value its 132, because
    AFAICT you only called nextval('s') 100 times, so why isn't it 100?
    My guess is that it seems to be related to code in "nextval_internal"
    (fetch = log = fetch + SEQ_LOG_VALS;) but it kind of defies
    expectations of the test, so if it really is correct then it needs
    commentary.
    
    Actually, I found other regression test code that deals with this:
    -- log_cnt can be higher if there is a checkpoint just at the right
    -- time, so just test for the expected range
    SELECT last_value, log_cnt IN (31, 32) AS log_cnt_ok, is_called FROM
    foo_seq_new;
    
    Do you have to do something similar? Or is this a bug? See my other
    review comments for function fetch_sequence_data in sequencesync.c
    
    ======
    99.
    Please also see the attached diffs patch which implements any nitpicks
    mentioned above.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  74. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-16T00:30:22Z

    Hi,
    
    I was reading back through this thread to find out how the proposed new
    command for refreshing sequences,  came about. The patch 0705 introduces a
    new command syntax for ALTER SUBSCRIPTION ... REFRESH SEQUENCES
    
    So now there are 2 forms of subscription refresh.
    
    #1. ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( refresh_option [=
    value] [, ... ] ) ]
    
    #2. ALTER SUBSCRIPTION name REFRESH SEQUENCES
    
    ~~~~
    
    IMO, that separation seems complicated. It leaves many questions like:
    * It causes a bit of initial confusion. e.g. When I saw the REFRESH
    SEQUENCES I first assumed that was needed because sequences were
    not covered by the existing REFRESH PUBLICATION
    * Why wasn't command #2 called ALTER SUBSCRIPTION REFRESH PUBLICATION
    SEQUENCES? E.g. missing keyword PUBLICATION. It seems inconsistent.
    * I expect sequence values can become stale pretty much immediately after
    command #1, so the user will want to use command #2 anyway...
    * ... but if command #2 also does add/remove changed sequences same as
    command #1 then what benefit was there of having the command #1 for
    sequences?
    * There is a separation of sequences (from tables) in command #2 but there
    is no separation currently possible in command #1. It seemed inconsistent.
    
    ~~~
    
    IIUC some of the goals I saw in the thread are to:
    * provide a way to fetch and refresh sequences that also keeps behaviors
    (e.g. copy_data etc.) consistent with the refresh of subscription tables
    * provide a way to fetch and refresh *only* sequences
    
    I felt you could just enhance the existing refresh command syntax (command
    #1), instead of introducing a new one it would be simpler and it would
    still meet those same objectives.
    
    Synopsis:
    ALTER SUBSCRIPTION name REFRESH PUBLICATION [TABLES | SEQUENCES | ALL] [
    WITH ( refresh_option [= value] [, ... ] ) ]
    
    My only change is the introduction of the optional "[TABLES | SEQUENCES |
    ALL]" clause.
    
    I believe that can do everything your current patch does, plus more:
    * Can refresh *only* TABLES if that is what you want (current patch 0705
    cannot do this)
    * Can refresh *only* SEQUENCES (same as current patch 0705 command #2)
    * Has better integration with refresh options like "copy_data" (current
    patch 0705 command #2 doesn't have options)
    * Existing REFRESH PUBLICATION syntax still works as-is. You can decide
    later what is PG18 default if the "[TABLES | SEQUENCES | ALL]" is omitted.
    
    ~~~
    
    More examples using proposed syntax.
    
    ex1.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION TABLES WITH (copy_data = false)
    - same as PG17 functionality for ALTER SUBSCRIPTION sub REFRESH PUBLICATION
    WITH (copy_data = false)
    
    ex2.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION TABLES WITH (copy_data = true)
    - same as PG17 functionality for ALTER SUBSCRIPTION sub REFRESH PUBLICATION
    WITH (copy_data = true)
    
    ex3.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION SEQUENCES WITH (copy data =
    false)
    - this adds/removes only sequences to pg_subscription_rel but doesn't
    update their sequence values
    
    ex4.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION SEQUENCES WITH (copy data = true)
    - this adds/removes only sequences to pg_subscription_rel and also updates
    all sequence values.
    - this is equivalent behaviour of what your current 0705 patch is doing for
    command #2, ALTER SUBSCRIPTION sub REFRESH SEQUENCES
    
    ex5.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION ALL WITH (copy_data = false)
    - this is equivalent behaviour of what your current 0705 patch is doing for
    command #1, ALTER SUBSCRIPTION sub REFRESH PUBLICATION WITH (copy_data =
    false)
    
    ex6.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION ALL WITH (copy_data = true)
    - this adds/removes tables and sequences and updates all table initial data
    sequence values.- I think it is equivalent to your current 0705 patch doing
    command #1 ALTER SUBSCRIPTION sub REFRESH PUBLICATION WITH (copy_data =
    true), followed by another command #2 ALTER SUBSCRIPTION sub REFRESH
    SEQUENCES
    
    ex7.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION SEQUENCES
    - Because default copy_data is true you do not need to specify options, so
    this is the same behaviour as your current 0705 patch command #2, ALTER
    SUBSCRIPTION sub REFRESH SEQUENCES.
    
    ~~~
    
    I hope this post was able to demonstrate that by enhancing the existing
    command:
    - it is less tricky to understand the separate command distinctions
    - there is more functionality/flexibility possible
    - there is better integration with the refresh options like copy_data
    - behaviour for tables/sequences is more consistent
    
    Anyway, it is just my opinion. Maybe there are some pitfalls I'm unaware of.
    
    Thoughts?
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  75. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-20T15:06:21Z

    On Wed, 10 Jul 2024 at 09:34, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > On Fri, Jul 5, 2024 at 9:58 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Thu, 4 Jul 2024 at 12:44, Peter Smith <smithpb2250@gmail.com> wrote:
    > > >
    > > > 1.
    > > > Should there be some new test for the view? Otherwise, AFAICT this
    > > > patch has no tests that will exercise the new function
    > > > pg_get_publication_sequences.
    > >
    > > pg_publication_sequences view uses pg_get_publication_sequences which
    > > will be tested with 3rd patch while creating subscription/refreshing
    > > publication sequences. I felt it is ok not to have a test here.
    > >
    >
    > OTOH, if there had been such a test here then the ("sequence = NIL")
    > bug in patch 0002 code would have been caught earlier in patch 0002
    > testing instead of later in patch 0003 testing. In general, I think
    > each patch should be self-contained w.r.t. to testing all of its new
    > code, but if you think another test here is overkill then I am fine
    > with that too.
    
    Moved these changes to 0003 patch where it is actually required.
    
    > //////////
    >
    > Meanwhile, here are my review comments for patch v20240705-0002
    
    All the comments are fixed and the attached v20240720 version patch
    has the changes for the same.
    
    Regards,
    Vignesh
    
  76. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-20T15:08:18Z

    On Wed, 10 Jul 2024 at 13:46, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Here are a few comments for patch v20240705-0003.
    >
    > (This is a WIP. I have only looked at the docs so far.)
    >
    > ======
    > doc/src/sgml/config.sgml
    >
    > nitpick - max_logical_replication_workers: /and sequence
    > synchornization worker/and a sequence synchornization worker/
    >
    > ======
    > doc/src/sgml/logical-replication.sgml
    >
    > nitpick - max_logical_replication_workers: re-order list of workers to
    > be consistent with other docs 1-apply,2-parallel,3-tablesync,4-seqsync
    >
    > ======
    > doc/src/sgml/ref/alter_subscription.sgml
    >
    > 1.
    > IIUC the existing "REFRESH PUBLICATION" command will fetch and sync
    > all new sequences, etc., and/or remove old ones no longer in the
    > publication. But current docs do not say anything at all about
    > sequences here. It should say something about sequence behaviour.
    >
    > ~~~
    >
    > 2.
    > For the existing "REFRESH PUBLICATION" there is a sub-option
    > "copy_data=true/false". Won't this need some explanation about how it
    > behaves for sequences? Or will there be another option
    > "copy_sequences=true/false".
    >
    > ~~~
    >
    > 3.
    > IIUC the main difference between REFRESH PUBLICATION and REFRESH
    > PUBLICATION SEQUENCES is that the 2nd command will try synchronize
    > with all the *existing* sequences to bring them to the same point as
    > on the publisher, but otherwise, they are the same command. If that is
    > correct understanding I don't think that distinction is made very
    > clear in the current docs.
    >
    > ~~~
    >
    > nitpick - the synopsis is misplaced. It should not be between ENABLE
    > and DISABLE. I moved it. Also, it should say "REFRESH PUBLICATION
    > SEQUENCES" because that is how the new syntax is defined in gram.y
    >
    > nitpick - REFRESH SEQUENCES. Renamed to "REFRESH PUBLICATION
    > SEQUENCES". And, shouldn't "from the publisher" say "with the
    > publisher"?
    >
    > nitpick - changed the varlistentry "id".
    >
    > ======
    > 99.
    > Please also see the attached diffs patch which implements any nitpicks
    > mentioned above.
    
    All these comments are handled in the v20240720 version patch attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm2vuO7Ya4QVTZKR9jY_mkFFcE_hKUJiXx4KUknPgGFjSg%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  77. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-20T15:18:16Z

    On Fri, 12 Jul 2024 at 08:22, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh. Here are the rest of my comments for patch v20240705-0003.
    > ======
    > src/backend/catalog/pg_subscription.c
    >
    > 1. GetSubscriptionSequences
    >
    > +/*
    > + * Get the sequences for the subscription.
    > + *
    > + * The returned list is palloc'ed in the current memory context.
    > + */
    >
    > Is that comment right? The palloc seems to be done in
    > CacheMemoryContext, not in the current context.
    
    This function is removed and GetSubscriptionRelations is being used instead.
    
    > ~
    >
    > 2.
    > The code is very similar to the other function
    > GetSubscriptionRelations(). In fact I did not understand how the 2
    > functions know what they are returning:
    >
    > E.g. how does GetSubscriptionRelations not return sequences too?
    > E.g. how does GetSubscriptionSequences not return relations too?
    
    GetSubscriptionRelations can be used, so removed the
    GetSubscriptionSequences function.
    
    >
    > 3. AlterSubscription_refresh
    >
    > - logicalrep_worker_stop(sub->oid, relid);
    > + /* Stop the worker if relation kind is not sequence*/
    > + if (relkind != RELKIND_SEQUENCE)
    > + logicalrep_worker_stop(sub->oid, relid);
    >
    > Can you give more reasons in the comment why skip the stop for sequence worker?
    >
    > ~
    >
    > nitpick - period and space in the comment
    >
    > ~~~
    >
    > 8. logicalrep_sequence_sync_worker_find
    >
    > +/*
    > + * Walks the workers array and searches for one that matches given
    > + * subscription id.
    > + *
    > + * We are only interested in the sequence sync worker.
    > + */
    > +LogicalRepWorker *
    > +logicalrep_sequence_sync_worker_find(Oid subid, bool only_running)
    >
    > There are other similar functions for walking the workers array to
    > search for a worker. Instead of having different functions for
    > different cases, wouldn't it be cleaner to combine these into a single
    > function, where you pass a parameter (e.g. a mask of worker types that
    > you are interested in finding)?
    
    I will address this in a future version once the patch has become more stable.
    > ~~~
    >
    > 11.
    > - Assert(is_tablesync_worker == OidIsValid(relid));
    > + Assert(is_tablesync_worker == OidIsValid(relid) ||
    > is_sequencesync_worker == OidIsValid(relid));
    >
    > IIUC there is only a single sequence sync worker for handling all the
    > sequences. So, what does the 'relid' actually mean here when there are
    > multiple sequences?
    
    Sequence sync workers will not have relid, modified the assert.
    
    > ~~~
    >
    > 12. logicalrep_seqsyncworker_failuretime
    > 12b.
    > Curious if this had to be a separate exit handler or if may this could
    > have been handled by the existing logicalrep_worker_onexit handler.
    > See also other review comments int this post about this area --
    > perhaps all this can be removed?
    
    This function cannot be combined with logicalrep_worker_onexit as this
    function should be called only in failure case and this exit handler
    should be removed in case of success case.
    
    This cannot be removed because of the following reason:
    Consider the following situation: a sequence sync worker starts and
    then encounters a failure while syncing sequences. At the same time, a
    user initiates a "refresh publication sequences" operation. Given only
    the start time, it's not possible to distinguish whether the sequence
    sync worker failed or completed successfully. This is because the
    "refresh publication sequences" operation would have re-added the
    sequences, making it unclear whether the sync worker's failure or
    success occurred.
    
    >
    > 14.
    > The reason for the addition logic "(last_value + log_cnt)" is not
    > obvious. I am guessing it might be related to code from
    > 'nextval_internal' (fetch = log = fetch + SEQ_LOG_VALS;) but it is
    > complicated. It is unfortunate that the field 'log_cnt' seems hardly
    > commented anywhere at all.
    >
    > Also, I am not 100% sure if I trust the logic in the first place. The
    > caller of this function is doing:
    > sequence_value = fetch_sequence_data(conn, remoteid, &lsn);
    > /* sets the sequence with sequence_value */
    > SetSequenceLastValue(RelationGetRelid(rel), sequence_value);
    >
    > Won't that mean you can get to a situation where subscriber-side
    > result of lastval('s') can be *ahead* from lastval('s') on the
    > publisher? That doesn't seem good.
    
    Added comments for "last_value + log_cnt"
    Yes it can be ahead in subscribers. This will happen because every
    change of the sequence is not wal logged. It is WAL logged once in
    SEQ_LOG_VALS. This was discussed earlier and the sequence value being
    ahead was ok.
    https://www.postgresql.org/message-id/CA%2BTgmoaVLiKDD5vr1bzL-rxhMA37KCS_2xrqjbKVwGyqK%2BPCXQ%40mail.gmail.com
    
    > 15.
    > + /*
    > + * Logical replication of sequences is based on decoding WAL records,
    > + * describing the "next" state of the sequence the current state in the
    > + * relfilenode is yet to reach. But during the initial sync we read the
    > + * current state, so we need to reconstruct the WAL record logged when we
    > + * started the current batch of sequence values.
    > + *
    > + * Otherwise we might get duplicate values (on subscriber) if we failed
    > + * over right after the sync.
    > + */
    > + sequence_value = fetch_sequence_data(conn, remoteid, &lsn);
    > +
    > + /* sets the sequence with sequence_value */
    > + SetSequenceLastValue(RelationGetRelid(rel), sequence_value);
    >
    > (This is related to some earlier review comment #14 above). IMO all
    > this tricky commentary belongs in the function header of
    > "fetch_sequence_data", where it should be describing that function's
    > return value.
    
    Moved it to fetch_sequence_data where pg_sequence_state is called to
    avoid any confusion
    
    > 17.
    > Also, where does the number 100 come from? Why not 1000? Why not 10?
    > Why have batching at all? Maybe there should be some comment to
    > describe the reason and the chosen value.
    
    Added a comment for this. I will do one round of testing with few
    values and see if this value needs to be changed. I will share it
    later.
    
    > 20.
    > + char relkind;
    > +
    > + if (!started_tx)
    > + {
    > + StartTransactionCommand();
    > + started_tx = true;
    > + }
    > +
    > + relkind = get_rel_relkind(rstate->relid);
    > + if (relkind == RELKIND_SEQUENCE)
    > + continue;
    >
    > I am wondering is it possible to put the relkind check can come
    > *before* the TX code here, because in case there are *only* sequences
    > then maybe every would be skipped and there would have been no need
    > for any TX at all in the first place.
    
    We need to start the transaction before calling get_rel_relkind, else
    it will assert in SearchCatCacheInternal. So Skipping this.
    
    > 21.
    > + if (!started_tx)
    > + {
    > + StartTransactionCommand();
    > + started_tx = true;
    > + }
    > +
    > + relkind = get_rel_relkind(rstate->relid);
    > + if (relkind != RELKIND_SEQUENCE || rstate->state != SUBREL_STATE_INIT)
    > + continue;
    >
    > Wondering (like in review comment #20) if it is possible to swap those
    > because maybe there was no reason for any TX if the other condition
    > would always continue.
    
    As transaction is required before calling get_rel_relkind, this cannot
    be changed. So skipping this.
    
    > ~~~
    >
    > 22.
    > + if (nsyncworkers < max_sync_workers_per_subscription)
    > + {
    > + TimestampTz now = GetCurrentTimestamp();
    > + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    > + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    > +    now, wal_retrieve_retry_interval))
    > + {
    > + MyLogicalRepWorker->sequencesync_failure_time = 0;
    >
    > It seems to me that storing 'sequencesync_failure_time' logic may be
    > unnecessarily complicated. Can't the same "throttling" be achieved by
    > storing the synchronization worker 'start time' instead of 'fail
    > time', in which case then you won't have to mess around with
    > considering if the sync worker failed or just exited normally etc? You
    > might also be able to remove all the
    > logicalrep_seqsyncworker_failuretime() exit handler code.
    
    Consider the following situation: a sequence sync worker starts and
    then encounters a failure while syncing sequences. At the same time, a
    user initiates a "refresh publication sequences" operation. Given only
    the start time, it's not possible to distinguish whether the sequence
    sync worker failed or completed successfully. This is because the
    "refresh publication sequences" operation would have re-added the
    sequences, making it unclear whether the sync worker's failure or
    success occurred.
    
    > 28b.
    > Can you explain why the expected sequence value its 132, because
    > AFAICT you only called nextval('s') 100 times, so why isn't it 100?
    > My guess is that it seems to be related to code in "nextval_internal"
    > (fetch = log = fetch + SEQ_LOG_VALS;) but it kind of defies
    > expectations of the test, so if it really is correct then it needs
    > commentary.
    
    I felt adding comments for one of the tests should be enough, So I did
    not add the comment for all of the tests.
    
    > Actually, I found other regression test code that deals with this:
    > -- log_cnt can be higher if there is a checkpoint just at the right
    > -- time, so just test for the expected range
    > SELECT last_value, log_cnt IN (31, 32) AS log_cnt_ok, is_called FROM
    > foo_seq_new;
    >
    > Do you have to do something similar? Or is this a bug? See my other
    > review comments for function fetch_sequence_data in sequencesync.c
    
    The comments in nextval_internal says:
     * If this is the first nextval after a checkpoint, we must force a new
     * WAL record to be written anyway, else replay starting from the
     * checkpoint would fail to advance the sequence past the logged values.
     * In this case we may as well fetch extra values.
    
    I have increased the checkpoint for this test, so this issue will not occur.
    
    All the other comments were fixed and the same is available in the
    v20240720 version attached at [1].
    
    [1] - https://www.postgresql.org/message-id/CALDaNm2vuO7Ya4QVTZKR9jY_mkFFcE_hKUJiXx4KUknPgGFjSg%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  78. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-23T05:32:50Z

    Here are some review comments for patch v20240720-0002.
    
    ======
    1. Commit message:
    
    1a.
    The commit message is stale. It is still referring to functions and
    views that have been moved to patch 0003.
    
    1b.
    "ALL SEQUENCES" is not a command. It is a clause of the CREATE
    PUBLICATION command.
    
    ======
    doc/src/sgml/ref/create_publication.sgml
    
    nitpick - publication name in the example /allsequences/all_sequences/
    
    ======
    src/bin/psql/describe.c
    
    2. describeOneTableDetails
    
    Although it's not the fault of this patch, this patch propagates the
    confusion of 'result' versus 'res'. Basically, I did not understand
    the need for the variable 'result'. There is already a "PGResult
    *res", and unless I am mistaken we can just keep re-using that instead
    of introducing a 2nd variable having almost the same name and purpose.
    
    ~
    
    nitpick - comment case
    nitpick - rearrange comment
    
    ======
    src/test/regress/expected/publication.out
    
    (see publication.sql)
    
    ======
    src/test/regress/sql/publication.sql
    
    nitpick - tweak comment
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  79. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-23T09:34:42Z

    On Tue, 16 Jul 2024 at 06:00, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi,
    >
    > I was reading back through this thread to find out how the proposed new command for refreshing sequences,  came about. The patch 0705 introduces a new command syntax for ALTER SUBSCRIPTION ... REFRESH SEQUENCES
    >
    > So now there are 2 forms of subscription refresh.
    >
    > #1. ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( refresh_option [= value] [, ... ] ) ]
    
    This is correct.
    
    > #2. ALTER SUBSCRIPTION name REFRESH SEQUENCES
    
    This is not correct, it is actually "ALTER SUBSCRIPTION name REFRESH
    PUBLICATION SEQUENCES"
    
    > ~~~~
    >
    > IMO, that separation seems complicated. It leaves many questions like:
    > * It causes a bit of initial confusion. e.g. When I saw the REFRESH SEQUENCES I first assumed that was needed because sequences were not covered by the existing REFRESH PUBLICATION
    > * Why wasn't command #2 called ALTER SUBSCRIPTION REFRESH PUBLICATION SEQUENCES? E.g. missing keyword PUBLICATION. It seems inconsistent.
    
    This is not correct, the existing implementation uses the key word
    PUBLICATION, the actual syntax is:
    "ALTER SUBSCRIPTION name REFRESH PUBLICATION SEQUENCES"
    
    > * I expect sequence values can become stale pretty much immediately after command #1, so the user will want to use command #2 anyway...
    
    Yes
    
    > * ... but if command #2 also does add/remove changed sequences same as command #1 then what benefit was there of having the command #1 for sequences?
    > * There is a separation of sequences (from tables) in command #2 but there is no separation currently possible in command #1. It seemed inconsistent.
    
    This can be enhanced if required. It is not included as of now because
    I'm not sure if there is such a use case in case of tables.
    
    > ~~~
    >
    > IIUC some of the goals I saw in the thread are to:
    > * provide a way to fetch and refresh sequences that also keeps behaviors (e.g. copy_data etc.) consistent with the refresh of subscription tables
    > * provide a way to fetch and refresh *only* sequences
    >
    > I felt you could just enhance the existing refresh command syntax (command #1), instead of introducing a new one it would be simpler and it would still meet those same objectives.
    >
    > Synopsis:
    > ALTER SUBSCRIPTION name REFRESH PUBLICATION [TABLES | SEQUENCES | ALL] [ WITH ( refresh_option [= value] [, ... ] ) ]
    >
    > My only change is the introduction of the optional "[TABLES | SEQUENCES | ALL]" clause.
    >
    > I believe that can do everything your current patch does, plus more:
    > * Can refresh *only* TABLES if that is what you want (current patch 0705 cannot do this)
    > * Can refresh *only* SEQUENCES (same as current patch 0705 command #2)
    > * Has better integration with refresh options like "copy_data" (current patch 0705 command #2 doesn't have options)
    > * Existing REFRESH PUBLICATION syntax still works as-is. You can decide later what is PG18 default if the "[TABLES | SEQUENCES | ALL]" is omitted.
    >
    > ~~~
    >
    > More examples using proposed syntax.
    >
    > ex1.
    > ALTER SUBSCRIPTION sub REFRESH PUBLICATION TABLES WITH (copy_data = false)
    > - same as PG17 functionality for ALTER SUBSCRIPTION sub REFRESH PUBLICATION WITH (copy_data = false)
    >
    > ex2.
    > ALTER SUBSCRIPTION sub REFRESH PUBLICATION TABLES WITH (copy_data = true)
    > - same as PG17 functionality for ALTER SUBSCRIPTION sub REFRESH PUBLICATION WITH (copy_data = true)
    >
    > ex3.
    > ALTER SUBSCRIPTION sub REFRESH PUBLICATION SEQUENCES WITH (copy data = false)
    > - this adds/removes only sequences to pg_subscription_rel but doesn't update their sequence values
    >
    > ex4.
    > ALTER SUBSCRIPTION sub REFRESH PUBLICATION SEQUENCES WITH (copy data = true)
    > - this adds/removes only sequences to pg_subscription_rel and also updates all sequence values.
    > - this is equivalent behaviour of what your current 0705 patch is doing for command #2, ALTER SUBSCRIPTION sub REFRESH SEQUENCES
    >
    > ex5.
    > ALTER SUBSCRIPTION sub REFRESH PUBLICATION ALL WITH (copy_data = false)
    > - this is equivalent behaviour of what your current 0705 patch is doing for command #1, ALTER SUBSCRIPTION sub REFRESH PUBLICATION WITH (copy_data = false)
    >
    > ex6.
    > ALTER SUBSCRIPTION sub REFRESH PUBLICATION ALL WITH (copy_data = true)
    > - this adds/removes tables and sequences and updates all table initial data sequence values.- I think it is equivalent to your current 0705 patch doing
    > command #1 ALTER SUBSCRIPTION sub REFRESH PUBLICATION WITH (copy_data = true), followed by another command #2 ALTER SUBSCRIPTION sub REFRESH SEQUENCES
    >
    > ex7.
    > ALTER SUBSCRIPTION sub REFRESH PUBLICATION SEQUENCES
    > - Because default copy_data is true you do not need to specify options, so this is the same behaviour as your current 0705 patch command #2, ALTER SUBSCRIPTION sub REFRESH SEQUENCES.
    
    I felt ex:4 is equivalent to command #2 "ALTER SUBSCRIPTION name
    REFRESH PUBLICATION SEQUENCES" and ex:3 just updates the
    pg_subscription_rel. But I'm not seeing an equivalent for "ALTER
    SUBSCRIPTION name REFRESH PUBLICATION with (copy_data = true)" which
    will identify and remove the stale entries and add entries/synchronize
    the sequences for the newly added sequences in the publisher.
    
    Regards,
    Vignesh
    
    
    
    
  80. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-24T03:46:52Z

    Hi, here are some review comments for patch v20240720-0003.
    
    This review is a WIP. This post is only about the docs (*.sgml) of patch 0003.
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    1. REFRESH PUBLICATION and copy_data
    nitpicks:
    - IMO the "synchronize the sequence data" info was misleading because
    synchronization should only occur when copy_data=true.
    - I also felt it was strange to mention pg_subscription_rel for
    sequences, but not for tables. I modified this part too.
    - Then I moved the information about re/synchronization of sequences
    into the "copy_data" part.
    - And added another link to ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES
    
    Anyway, in summary, I have updated this page quite a lot according to
    my understanding. Please take a look at the attached nitpick for my
    suggestions.
    
    nitpick - /The supported options are:/The only supported option is:/
    
    ~~~
    
    2. REFRESH PUBLICATION SEQUENCES
    nitpick - tweaked the wording
    nitpicK - typo /syncronizes/synchronizes/
    
    ======
    3. catalogs.sgml
    
    IMO something is missing in Section "1.55. pg_subscription_rel".
    
    Currently, this page only talks of relations/tables, but I think it
    should mention "sequences" here too, particularly since now we are
    linking to here from ALTER SUBSCRIPTION when talking about sequences.
    
    ======
    99.
    Please see the attached diffs patch which implements any nitpicks
    mentioned above.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  81. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-07-24T06:22:49Z

    On Wed, Jul 24, 2024 at 9:17 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    
    I had a look at patches v20240720* (considering these as the latest
    one) and tried to do some basic testing (WIP). Few comments:
    
    1)
    I see 'last_value' is updated wrongly after create-sub.  Steps:
    
    -----------
    pub:
    CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    SELECT nextval('myseq0');
    SELECT nextval('myseq0');
    --last_value on pub is 105
    select * from pg_sequences;
    create publication pub1 for all tables, sequences;
    
    Sub:
    CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    create subscription sub1 connection 'dbname=postgres host=localhost
    user=shveta port=5433' publication pub1;
    
    --check 'r' state is reached
    select pc.relname, pr.srsubstate, pr.srsublsn from pg_subscription_rel
    pr, pg_class pc where (pr.srrelid = pc.oid);
    
    --check 'last_value', it shows some random value as 136
    select * from pg_sequences;
    -----------
    
    2)
    I can use 'for all sequences' only with 'for all tables' and can not
    use it with the below. Shouldn't it be allowed?
    
    create publication pub2 for tables in schema public, for all sequences;
    create publication pub2 for table t1, for all sequences;
    
    3)
    preprocess_pub_all_objtype_list():
    Do we need 'alltables_specified' and 'allsequences_specified' ? Can't
    we make a repetition check using *alltables and *allsequences?
    
    4) patch02's commit msg says : 'Additionally, a new system view,
    pg_publication_sequences, has been introduced'
    But it is not part of patch002.
    
    thanks
    Shveta
    
    
    
    
  82. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-24T06:37:01Z

    On Wed, 24 Jul 2024 at 09:17, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi, here are some review comments for patch v20240720-0003.
    >
    > This review is a WIP. This post is only about the docs (*.sgml) of patch 0003.
    >
    > 3. catalogs.sgml
    >
    > IMO something is missing in Section "1.55. pg_subscription_rel".
    >
    > Currently, this page only talks of relations/tables, but I think it
    > should mention "sequences" here too, particularly since now we are
    > linking to here from ALTER SUBSCRIPTION when talking about sequences.
    
    Modified it to mention sequences too.
    
    I have merged the rest of the nitpicks suggested by you.
    The attached v20240724 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  83. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-24T06:40:01Z

    On Tue, 23 Jul 2024 at 11:03, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Here are some review comments for patch v20240720-0002.
    >
    > ======
    > 1. Commit message:
    >
    > 1a.
    > The commit message is stale. It is still referring to functions and
    > views that have been moved to patch 0003.
    
    Modified
    
    > 1b.
    > "ALL SEQUENCES" is not a command. It is a clause of the CREATE
    > PUBLICATION command.
    
    Modified
    
    > src/bin/psql/describe.c
    >
    > 2. describeOneTableDetails
    >
    > Although it's not the fault of this patch, this patch propagates the
    > confusion of 'result' versus 'res'. Basically, I did not understand
    > the need for the variable 'result'. There is already a "PGResult
    > *res", and unless I am mistaken we can just keep re-using that instead
    > of introducing a 2nd variable having almost the same name and purpose.
    
    This is intentional, we cannot clear res as it will be used in many
    places of printTable like in
    printTable->print_aligned_text->pg_wcssize which was earlier stored
    from printTableAddCell calls.
    
    The rest of the nitpicks comments were merged.
    The v20240724 version patch attached at [1] has the changes for the same.
    
    [1] - https://www.postgresql.org/message-id/CALDaNm1uncevCSMqo5Nk%3DtqqV_o3KNH_jwp8URiGop_nPC8BTg%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  84. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-07-24T09:20:29Z

    On Wed, Jul 24, 2024 at 11:52 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Wed, Jul 24, 2024 at 9:17 AM Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    >
    > I had a look at patches v20240720* (considering these as the latest
    > one) and tried to do some basic testing (WIP). Few comments:
    >
    > 1)
    > I see 'last_value' is updated wrongly after create-sub.  Steps:
    >
    > -----------
    > pub:
    > CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    > SELECT nextval('myseq0');
    > SELECT nextval('myseq0');
    > --last_value on pub is 105
    > select * from pg_sequences;
    > create publication pub1 for all tables, sequences;
    >
    > Sub:
    > CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    > create subscription sub1 connection 'dbname=postgres host=localhost
    > user=shveta port=5433' publication pub1;
    >
    > --check 'r' state is reached
    > select pc.relname, pr.srsubstate, pr.srsublsn from pg_subscription_rel
    > pr, pg_class pc where (pr.srrelid = pc.oid);
    >
    > --check 'last_value', it shows some random value as 136
    > select * from pg_sequences;
    
    Okay, I see that in fetch_remote_sequence_data(), we are inserting
    'last_value + log_cnt' fetched from remote as 'last_val' on subscriber
    and thus leading to above behaviour. I did not understand why this is
    done? This may result into issue when we insert data into a table with
    identity column on subscriber (whose internal sequence is replicated);
    the identity column in this case will end up having wrong value.
    
    thanks
    Shveta
    
    
    
    
  85. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-25T03:22:26Z

    On Wed, 24 Jul 2024 at 11:53, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Wed, Jul 24, 2024 at 9:17 AM Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    >
    > I had a look at patches v20240720* (considering these as the latest
    > one) and tried to do some basic testing (WIP). Few comments:
    >
    > 1)
    > I see 'last_value' is updated wrongly after create-sub.  Steps:
    >
    > -----------
    > pub:
    > CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    > SELECT nextval('myseq0');
    > SELECT nextval('myseq0');
    > --last_value on pub is 105
    > select * from pg_sequences;
    > create publication pub1 for all tables, sequences;
    >
    > Sub:
    > CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    > create subscription sub1 connection 'dbname=postgres host=localhost
    > user=shveta port=5433' publication pub1;
    >
    > --check 'r' state is reached
    > select pc.relname, pr.srsubstate, pr.srsublsn from pg_subscription_rel
    > pr, pg_class pc where (pr.srrelid = pc.oid);
    >
    > --check 'last_value', it shows some random value as 136
    > select * from pg_sequences;
    
    Earlier I was setting sequence value with the value of publisher +
    log_cnt, that is why the difference is there. On further thinking
    since we are not supporting incremental replication of sequences, so
    no plugin usage is involved which requires the special decoding last
    value and log_count. I felt we can use the exact sequence last value
    and log count to generate the similar sequence value. So Now I have
    changed it to get the last_value and log_count from the publisher and
    set it to the same values.
    
    >
    > 2)
    > I can use 'for all sequences' only with 'for all tables' and can not
    > use it with the below. Shouldn't it be allowed?
    >
    > create publication pub2 for tables in schema public, for all sequences;
    > create publication pub2 for table t1, for all sequences;
    
    I feel this can be added as part of a later version while supporting
    "add/drop/set sequence and add/drop/set sequences in schema" once the
    patch is stable.
    
    > 3)
    > preprocess_pub_all_objtype_list():
    > Do we need 'alltables_specified' and 'allsequences_specified' ? Can't
    > we make a repetition check using *alltables and *allsequences?
    
    Modified
    
    > 4) patch02's commit msg says : 'Additionally, a new system view,
    > pg_publication_sequences, has been introduced'
    > But it is not part of patch002.
    
    This is removed now
    
    The attached v20240725 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  86. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-07-25T06:38:19Z

    On Thu, Jul 25, 2024 at 9:06 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > The attached v20240725 version patch has the changes for the same.
    
    Thank You for addressing the comments. Please review below issues:
    
    1) Sub ahead of pub due to wrong initial sync of last_value for
    non-incremented sequences. Steps at [1]
    2) Sequence's min value is not honored on sub during replication. Steps at [2]
    
    [1]:
    -----------
    on PUB:
    CREATE SEQUENCE myseq001 INCREMENT 5 START 100;
    SELECT * from pg_sequences; -->shows last_val as NULL
    
    on SUB:
    CREATE SEQUENCE myseq001 INCREMENT 5 START 100;
    SELECT * from pg_sequences; -->correctly shows last_val as NULL
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    SELECT * from pg_sequences;  -->wrongly updates last_val to 100; it is
    still NULL on Pub.
    
    Thus , SELECT nextval('myseq001') on pub gives 100, while on sub gives 105.
    -----------
    
    
    [2]:
    -----------
    Pub:
    CREATE SEQUENCE myseq0 INCREMENT 5 START 10;
    SELECT * from pg_sequences;
    
    Sub:
    CREATE SEQUENCE myseq0 INCREMENT 5 MINVALUE 100;
    
    Pub:
    SELECT nextval('myseq0');
    SELECT nextval('myseq0');
    
    Sub:
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    --check 'last_value', it is 15 while min_value is 100
    SELECT * from pg_sequences;
    -----------
    
    thanks
    Shveta
    
    
    
    
  87. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-25T07:24:28Z

    Hi, here are more review comments for patch v20240720-0003.
    
    ======
    src/backend/catalog/pg_subscription.c
    
    (Numbers are starting at #4 because this is a continuation of the docs review)
    
    4. GetSubscriptionRelations
    
    nitpick - rearranged the function header comment
    
    ~
    
    5.
    TBH, I'm thinking that just passing 2 parameters:
    - bool get_tables
    - bool get_sequences
    where one or both can be true, would have resulted in simpler code,
    instead of introducing this new enum SubscriptionRelKind.
    
    ~
    
    6.
    The 'not_all_relations' parameter/logic feels really awkward. IMO it
    needs a better name and reverse the meaning to remove all the "nots".
    
    For example, commenting it and calling it like below could be much simpler.
    
    'all_relations'
    If returning sequences, if all_relations=true get all sequences,
    otherwise only get sequences that are in 'init' state.
    If returning tables, if all_relation=true get all tables, otherwise
    only get tables that have not reached 'READY' state.
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    AlterSubscription_refresh:
    
    nitpick - this function comment is difficult to understand. I've
    rearranged it a bit but it could still do with some further
    improvement.
    nitpick - move some code comments
    nitpick - I adjusted the "stop worker" comment slightly. Please check
    it is still correct.
    nitpick - add a blank line
    
    ~
    
    7.
    The logic seems over-complicated. For example, why is the sequence
    list *always* fetched, but the tables list is only sometimes fetched?
    Furthermore, this 'refresh_all_sequences' parameter seems to have a
    strange interference with tables (e.g. even though it is possible to
    refresh all tables and sequences at the same time). It is as if the
    meaning is 'refresh_publication_sequences' yet it is not called that
    (???)
    
    These gripes may be related to my other thread [1] about the new ALTER
    syntax. (I feel that there should be the ability to refresh ALL TABLES
    or ALL SEQUENCES independently if the user wants to). IIUC, it would
    simplify this function logic as well as being more flexible. Anyway, I
    will leave the discussion about syntax to that other thread.
    
    ~
    
    8.
    + if (relkind != RELKIND_SEQUENCE)
    + logicalrep_worker_stop(sub->oid, relid);
    
      /*
      * For READY state, we would have already dropped the
      * tablesync origin.
      */
    - if (state != SUBREL_STATE_READY)
    + if (state != SUBREL_STATE_READY && relkind != RELKIND_SEQUENCE)
    
    It might be better to have a single "if (relkind != RELKIND_SEQUENCE)"
    here and combine both of these codes under that.
    
    ~
    
    9.
      ereport(DEBUG1,
    - (errmsg_internal("table \"%s.%s\" removed from subscription \"%s\"",
    + (errmsg_internal("%s \"%s.%s\" removed from subscription \"%s\"",
    + get_namespace_name(get_rel_namespace(relid)),
    + get_rel_name(relid),
    + sub->name,
    + get_rel_relkind(relid) == RELKIND_SEQUENCE ? "sequence" : "table")));
    
    IIUC prior conDitions mean get_rel_relkind(relid) == RELKIND_SEQUENCE
    will be impossible here.
    
    ~~~
    
    10. AlterSubscription
    
    + PreventInTransactionBlock(isTopLevel, "ALTER SUBSCRIPTION ...
    REFRESH PUBLICATION SEQUENCES");
    
    IIUC the docs page for ALTER SUBSCRIPTION was missing this information
    about "REFRESH PUBLICATION SEQUENCES" in transactions. Docs need more
    updates.
    
    ======
    src/backend/replication/logical/launcher.c
    
    logicalrep_worker_find:
    nitpick - tweak comment to say "or" instead of "and"
    
    ~~~
    
    11.
    +/*
    + * Return the pid of the apply worker for one that matches given
    + * subscription id.
    + */
    +static LogicalRepWorker *
    +logicalrep_apply_worker_find(Oid subid, bool only_running)
    
    The function comment is wrong. This is not returning a PID.
    
    ~~~
    
    12.
    + if (is_sequencesync_worker)
    + Assert(!OidIsValid(relid));
    
    Should we the Assert to something more like:
    Assert(!is_sequencesync_worker || !OidIsValid(relid));
    
    Otherwise, in NODEBUG current code will compile into an empty
    condition statement, which is a bit odd.
    
    ~~~
    
    logicalrep_seqsyncworker_failuretime:
    nitpick - tweak function comment
    nitpick - add blank line
    
    ======
    .../replication/logical/sequencesync.c
    
    13. fetch_remote_sequence_data
    
    The "current state" mentioned in the function comment is a bit vague.
    Can't tell from this comment what it is returning without looking
    deeper into the function code.
    
    ~
    
    nitpick - typo "scenarios" in comment
    
    ~~~
    
    copy_sequence:
    nitpick - typo "withe" in function comment
    nitpick - typo /retreived/retrieved/
    nitpick - add/remove blank lines
    
    ~~~
    
    LogicalRepSyncSequences:
    nitpick - move a comment.
    nitpick - remove blank line
    
    14.
    + /*
    + * Verify whether the current batch of sequences is synchronized or if
    + * there are no remaining sequences to synchronize.
    + */
    + if ((((curr_seq + 1) % MAX_SEQUENCES_SYNC_PER_BATCH) == 0) ||
    + (curr_seq + 1) == seq_count)
    
    
    All this "curr_seq + 1" maths seems unnecessarily tricky. Can't we
    just increment the cur_seq? before this calculation?
    
    ~
    
    nitpick - simplify the comment about batching
    nitpick - added a comment to the commit
    
    ======
    src/backend/replication/logical/tablesync.c
    
    finish_sync_worker:
    nitpick - added an Assert so the if/else is less risky.
    nitpick - modify the comment about failure time when it is a clean exit
    
    ~~~
    
    15. process_syncing_sequences_for_apply
    
    + /* We need up-to-date sync state info for subscription sequences here. */
    + FetchTableStates(&started_tx, SUB_REL_KIND_ALL);
    
    Should that say SUB_REL_KIND_SEQUENCE?
    
    ~
    
    16.
    + /*
    + * If there are free sync worker slot(s), start a new sequence
    + * sync worker, and break from the loop.
    + */
    + if (nsyncworkers < max_sync_workers_per_subscription)
    
    Should this "if" have some "else" code to log a warning if we have run
    out of free workers? Otherwise, how will the user know that the system
    may need tuning?
    
    ~~~
    
    17. FetchTableStates
    
      /* Fetch all non-ready tables. */
    - rstates = GetSubscriptionRelations(MySubscription->oid, true);
    + rstates = GetSubscriptionRelations(MySubscription->oid, rel_type, true);
    
    This feels risky. IMO there needs to be some prior Assert about the
    rel_type. For example, if it happened to be SUB_REL_KIND_SEQUENCE then
    this function code doesn't seem to make sense.
    
    ~~~
    
    ======
    src/backend/replication/logical/worker.c
    
    18. SetupApplyOrSyncWorker
    
    +
    + if (isSequenceSyncWorker(MyLogicalRepWorker))
    + before_shmem_exit(logicalrep_seqsyncworker_failuretime, (Datum) 0);
    
    Probably that should be using macro am_sequencesync_worker(), right?
    
    ======
    src/include/catalog/pg_subscription_rel.h
    
    19.
    +typedef enum
    +{
    + SUB_REL_KIND_TABLE,
    + SUB_REL_KIND_SEQUENCE,
    + SUB_REL_KIND_ALL,
    +} SubscriptionRelKind;
    +
    
    I was not sure how helpful this is; it might not be needed. e.g. see
    review comment for GetSubscriptionRelations
    
    ~~~
    
    20.
    +extern List *GetSubscriptionRelations(Oid subid, SubscriptionRelKind reltype,
    +   bool not_ready);
    
    There is a mismatch with the ‘not_ready’ parameter name here and in
    the function implementation
    
    ======
    src/test/subscription/t/034_sequences.pl
    
    nitpick - removed a blank line
    
    ======
    99.
    Please also see the attached diffs patch which implements all the
    nitpicks mentioned above.
    
    ======
    [1] syntax - https://www.postgresql.org/message-id/CAHut%2BPuFH1OCj-P1UKoRQE2X4-0zMG%2BN1V7jdn%3DtOQV4RNbAbw%40mail.gmail.com
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  88. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-07-25T10:10:58Z

    On Thu, Jul 25, 2024 at 12:08 PM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Thu, Jul 25, 2024 at 9:06 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached v20240725 version patch has the changes for the same.
    >
    > Thank You for addressing the comments. Please review below issues:
    >
    > 1) Sub ahead of pub due to wrong initial sync of last_value for
    > non-incremented sequences. Steps at [1]
    > 2) Sequence's min value is not honored on sub during replication. Steps at [2]
    
    One more issue:
    3)  Sequence datatype's range is not honored on sub during
    replication, while it is honored for tables.
    
    
    Behaviour for tables:
    ---------------------
    Pub: create table tab1( i integer);
    Sub: create table tab1( i smallint);
    
    Pub: insert into tab1 values(generate_series(1, 32768));
    
    Error on sub:
    2024-07-25 10:38:06.446 IST [178680] ERROR:  value "32768" is out of
    range for type smallint
    
    ---------------------
    Behaviour for sequences:
    ---------------------
    
    Pub:
    CREATE SEQUENCE myseq_i as integer INCREMENT 10000 START 1;
    
    Sub:
    CREATE SEQUENCE myseq_i as smallint INCREMENT 10000 START 1;
    
    Pub:
    SELECT nextval('myseq_i');
    SELECT nextval('myseq_i');
    SELECT nextval('myseq_i');
    SELECT nextval('myseq_i');
    SELECT nextval('myseq_i'); -->brings value to 40001
    
    Sub:
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    SELECT * from pg_sequences;  -->last_val reached till 40001, while the
    range is till  32767.
    
    thanks
    Shveta
    
    
    
    
  89. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-26T02:33:55Z

    Here are some review comments for latest patch v20240725-0002
    
    ======
    doc/src/sgml/ref/create_publication.sgml
    
    nitpick - tweak to the description of the example.
    
    ======
    src/backend/parser/gram.y
    
    preprocess_pub_all_objtype_list:
    nitpick - typo "allbjects_list"
    nitpick - reword function header
    nitpick - /alltables/all_tables/
    nitpick - /allsequences/all_sequences/
    nitpick - I think code is safe as-is because makeNode internally does
    palloc0, but OTOH adding Assert would be nicer just to remove any
    doubts.
    
    ======
    src/bin/psql/describe.c
    
    1.
    + /* Print any publications */
    + if (pset.sversion >= 180000)
    + {
    + int tuples = 0;
    
    No need to assign value 0 here, because this will be unconditionally
    assigned before use anyway.
    
    ~~~~
    
    2. describePublications
    
      has_pubviaroot = (pset.sversion >= 130000);
    + has_pubsequence = (pset.sversion >= 18000);
    
    That's a bug! Should be 180000, not 18000.
    
    ======
    
    And, please see the attached diffs patch, which implements the
    nitpicks mentioned above.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  90. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-26T06:16:30Z

    Hi Vignesh,
    
    There are still pending changes from my previous review of the
    0720-0003 patch [1], but here are some new review comments for your
    latest patch v20240525-0003.
    
    ======
    doc/src/sgml/catalogs.sgml
    
    nitpick - fix plurals and tweak the description.
    
    ~~~
    
    1.
       <para>
    -   This catalog only contains tables known to the subscription after running
    -   either <link linkend="sql-createsubscription"><command>CREATE
    SUBSCRIPTION</command></link> or
    -   <link linkend="sql-altersubscription"><command>ALTER SUBSCRIPTION
    ... REFRESH
    +   This catalog only contains tables and sequences known to the subscription
    +   after running either
    +   <link linkend="sql-createsubscription"><command>CREATE
    SUBSCRIPTION</command></link>
    +   or <link linkend="sql-altersubscription"><command>ALTER
    SUBSCRIPTION ... REFRESH
        PUBLICATION</command></link>.
       </para>
    
    Shouldn't this mention "REFRESH PUBLICATION SEQUENCES" too?
    
    ======
    src/backend/commands/sequence.c
    
    SetSequenceLastValue:
    nitpick - maybe change: /log_cnt/new_log_cnt/ for consistency with the
    other parameter, and to emphasise the old log_cnt is overwritten
    
    ======
    src/backend/replication/logical/sequencesync.c
    
    2.
    +/*
    + * fetch_remote_sequence_data
    + *
    + * Fetch sequence data (current state) from the remote node, including
    + * the latest sequence value from the publisher and the Page LSN for the
    + * sequence.
    + */
    +static int64
    +fetch_remote_sequence_data(WalReceiverConn *conn, Oid remoteid,
    +    int64 *log_cnt, XLogRecPtr *lsn)
    
    2a.
    Now you are also returning the 'log_cnt' but that is not mentioned by
    the function comment.
    
    ~
    
    2b.
    Is it better to name these returned by-ref ptrs like 'ret_log_cnt',
    and 'ret_lsn' to emphasise they are output variables? YMMV.
    
    ~~~
    
    3.
    + /* Process the sequence. */
    + slot = MakeSingleTupleTableSlot(res->tupledesc, &TTSOpsMinimalTuple);
    + while (tuplestore_gettupleslot(res->tuplestore, true, false, slot))
    
    This will have one-and-only-one tuple for the discovered sequence,
    won't it? So, why is this a while loop?
    
    ======
    src/include/commands/sequence.h
    
    nitpick - maybe change: /log_cnt/new_log_cnt/ (same as earlier in this post)
    
    ======
    src/test/subscription/t/034_sequences.pl
    
    4.
    Q. Should we be suspicious that log_cnt changes from '32' to '31', or
    is there a valid explanation? It smells like some calculation is
    off-by-one, but without debugging I can't tell if it is right or
    wrong.
    
    ======
    Please also see the attached diffs patch, which implements the
    nitpicks mentioned above.
    
    ======
    [1] 0720-0003 review -
    https://www.postgresql.org/message-id/CAHut%2BPsfsfzyBrmo8E43qFMp9_bmen2tuCsNYN8sX%3Dfa86SdfA%40mail.gmail.com
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  91. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-29T05:49:39Z

    On Thu, 25 Jul 2024 at 12:54, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi, here are more review comments for patch v20240720-0003.
    > 7.
    > The logic seems over-complicated. For example, why is the sequence
    > list *always* fetched, but the tables list is only sometimes fetched?
    > Furthermore, this 'refresh_all_sequences' parameter seems to have a
    > strange interference with tables (e.g. even though it is possible to
    > refresh all tables and sequences at the same time). It is as if the
    > meaning is 'refresh_publication_sequences' yet it is not called that
    > (???)
    >
    > These gripes may be related to my other thread [1] about the new ALTER
    > syntax. (I feel that there should be the ability to refresh ALL TABLES
    > or ALL SEQUENCES independently if the user wants to). IIUC, it would
    > simplify this function logic as well as being more flexible. Anyway, I
    > will leave the discussion about syntax to that other thread.
    
    1) ALTER SUBCRIPTION ... REFRESH PUBLICATION
    This command will refresh both tables and sequences. It will remove
    stale tables and sequences and include newly added tables and
    sequences.
    2) ALTER SUBCRIPTION ... REFRESH PUBLICATION SEQUENCES
    This command will refresh only sequences. It will remove stale
    sequences and synchronize all sequences including the existing
    sequences.
    So the table will be fetched only for the first command.
    I have changed refresh_publication_sequences parameter to tables,
    sequences, all_relations with this the function should be easier to
    understand and remove any confusions.
    
    > ~
    >
    > 9.
    >   ereport(DEBUG1,
    > - (errmsg_internal("table \"%s.%s\" removed from subscription \"%s\"",
    > + (errmsg_internal("%s \"%s.%s\" removed from subscription \"%s\"",
    > + get_namespace_name(get_rel_namespace(relid)),
    > + get_rel_name(relid),
    > + sub->name,
    > + get_rel_relkind(relid) == RELKIND_SEQUENCE ? "sequence" : "table")));
    >
    > IIUC prior conDitions mean get_rel_relkind(relid) == RELKIND_SEQUENCE
    > will be impossible here.
    
    Consider a scenario where logical replication is setup with sequences
    seq1, seq2.
    Now drop sequence seq1 and do "ALTER SUBSCRIPTION sub REFRESH PUBLICATION"
    It will hit this code to generate the log:
    DEBUG:  sequence "public.seq1" removed from subscription "test1"
    
    > ======
    > .../replication/logical/sequencesync.c
    >
    > 13. fetch_remote_sequence_data
    >
    > The "current state" mentioned in the function comment is a bit vague.
    > Can't tell from this comment what it is returning without looking
    > deeper into the function code.
    
    Added more comments to  clarify.
    
    > ~~~
    >
    > 15. process_syncing_sequences_for_apply
    >
    > + /* We need up-to-date sync state info for subscription sequences here. */
    > + FetchTableStates(&started_tx, SUB_REL_KIND_ALL);
    >
    > Should that say SUB_REL_KIND_SEQUENCE?
    
    We cannot pass SUB_REL_KIND_SEQUENCE here because the
    pg_subscription_rel table is shared between sequences and tables. As
    changes to either sequences or relations can affect the validity of
    relation states, we update both table_states_not_ready and
    sequence_states_not_ready simultaneously to ensure consistency, rather
    than updating them separately. I have removed the relation kind
    parameter now. Fetch tables is called to fetch all tables and
    sequences before calling process_syncing_tables_for_apply and
    process_syncing_sequences_for_apply now.
    
    > ~
    >
    > 16.
    > + /*
    > + * If there are free sync worker slot(s), start a new sequence
    > + * sync worker, and break from the loop.
    > + */
    > + if (nsyncworkers < max_sync_workers_per_subscription)
    >
    > Should this "if" have some "else" code to log a warning if we have run
    > out of free workers? Otherwise, how will the user know that the system
    > may need tuning?
    
    I felt no need to log here else we will get a lot of log messages
    which might not be required. Similar logic is used for tablesync to in
    process_syncing_tables_for_apply.
    
    > ~~~
    >
    > 17. FetchTableStates
    >
    >   /* Fetch all non-ready tables. */
    > - rstates = GetSubscriptionRelations(MySubscription->oid, true);
    > + rstates = GetSubscriptionRelations(MySubscription->oid, rel_type, true);
    >
    > This feels risky. IMO there needs to be some prior Assert about the
    > rel_type. For example, if it happened to be SUB_REL_KIND_SEQUENCE then
    > this function code doesn't seem to make sense.
    
    The pg_subscription_rel table is shared between sequences and tables.
    As changes to either sequences or relations can affect the validity of
    relation states, we update both table_states_not_ready and
    sequence_states_not_ready simultaneously to ensure consistency, rather
    than updating them separately. This will update both tables and
    sequences that should be synced.
    
    The rest of the comments are fixed. The attached v20240729 version
    patch has the changes for the same.
    
    Regards,
    Vignesh
    
  92. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-29T05:52:06Z

    On Fri, 26 Jul 2024 at 08:04, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Here are some review comments for latest patch v20240725-0002
    >
    > ======
    > doc/src/sgml/ref/create_publication.sgml
    >
    > nitpick - tweak to the description of the example.
    >
    > ======
    > src/backend/parser/gram.y
    >
    > preprocess_pub_all_objtype_list:
    > nitpick - typo "allbjects_list"
    > nitpick - reword function header
    > nitpick - /alltables/all_tables/
    > nitpick - /allsequences/all_sequences/
    > nitpick - I think code is safe as-is because makeNode internally does
    > palloc0, but OTOH adding Assert would be nicer just to remove any
    > doubts.
    >
    > ======
    > src/bin/psql/describe.c
    >
    > 1.
    > + /* Print any publications */
    > + if (pset.sversion >= 180000)
    > + {
    > + int tuples = 0;
    >
    > No need to assign value 0 here, because this will be unconditionally
    > assigned before use anyway.
    >
    > ~~~~
    >
    > 2. describePublications
    >
    >   has_pubviaroot = (pset.sversion >= 130000);
    > + has_pubsequence = (pset.sversion >= 18000);
    >
    > That's a bug! Should be 180000, not 18000.
    >
    > ======
    >
    > And, please see the attached diffs patch, which implements the
    > nitpicks mentioned above.
    
    These are handled in the v20240729 version attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm3SucGGLe-B-a_aqWNWQZ-yfxFTiAA0JyP-SwX4jq9Y3A%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  93. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-29T05:54:25Z

    On Fri, 26 Jul 2024 at 11:46, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > There are still pending changes from my previous review of the
    > 0720-0003 patch [1], but here are some new review comments for your
    > latest patch v20240525-0003.
    > 2b.
    > Is it better to name these returned by-ref ptrs like 'ret_log_cnt',
    > and 'ret_lsn' to emphasise they are output variables? YMMV.
    
    I felt this is ok as we have mentioned in function header too
    
    > ======
    > src/test/subscription/t/034_sequences.pl
    >
    > 4.
    > Q. Should we be suspicious that log_cnt changes from '32' to '31', or
    > is there a valid explanation? It smells like some calculation is
    > off-by-one, but without debugging I can't tell if it is right or
    > wrong.
    
     It works like this: for every 33 nextval we will get log_cnt as 0. So
    for 33 * 6(198) log_cnt will be 0, then for 199 log_cnt will be 32 and
    for 200 log_cnt will be 31. This pattern repeats, so this is ok.
    
    These are handled in the v20240729 version attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm3SucGGLe-B-a_aqWNWQZ-yfxFTiAA0JyP-SwX4jq9Y3A%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  94. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-29T10:47:35Z

    On Thu, 25 Jul 2024 at 12:08, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Thu, Jul 25, 2024 at 9:06 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached v20240725 version patch has the changes for the same.
    >
    > Thank You for addressing the comments. Please review below issues:
    >
    > 1) Sub ahead of pub due to wrong initial sync of last_value for
    > non-incremented sequences. Steps at [1]
    > 2) Sequence's min value is not honored on sub during replication. Steps at [2]
    >
    > [1]:
    > -----------
    > on PUB:
    > CREATE SEQUENCE myseq001 INCREMENT 5 START 100;
    > SELECT * from pg_sequences; -->shows last_val as NULL
    >
    > on SUB:
    > CREATE SEQUENCE myseq001 INCREMENT 5 START 100;
    > SELECT * from pg_sequences; -->correctly shows last_val as NULL
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > SELECT * from pg_sequences;  -->wrongly updates last_val to 100; it is
    > still NULL on Pub.
    >
    > Thus , SELECT nextval('myseq001') on pub gives 100, while on sub gives 105.
    > -----------
    >
    >
    > [2]:
    > -----------
    > Pub:
    > CREATE SEQUENCE myseq0 INCREMENT 5 START 10;
    > SELECT * from pg_sequences;
    >
    > Sub:
    > CREATE SEQUENCE myseq0 INCREMENT 5 MINVALUE 100;
    >
    > Pub:
    > SELECT nextval('myseq0');
    > SELECT nextval('myseq0');
    >
    > Sub:
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > --check 'last_value', it is 15 while min_value is 100
    > SELECT * from pg_sequences;
    
    Thanks for reporting this, these issues are fixed in the attached
    v20240730_2 version patch.
    
    Regards,
    Vignesh
    
  95. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-29T10:48:33Z

    On Thu, 25 Jul 2024 at 15:41, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Thu, Jul 25, 2024 at 12:08 PM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Thu, Jul 25, 2024 at 9:06 AM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > The attached v20240725 version patch has the changes for the same.
    > >
    > > Thank You for addressing the comments. Please review below issues:
    > >
    > > 1) Sub ahead of pub due to wrong initial sync of last_value for
    > > non-incremented sequences. Steps at [1]
    > > 2) Sequence's min value is not honored on sub during replication. Steps at [2]
    >
    > One more issue:
    > 3)  Sequence datatype's range is not honored on sub during
    > replication, while it is honored for tables.
    >
    >
    > Behaviour for tables:
    > ---------------------
    > Pub: create table tab1( i integer);
    > Sub: create table tab1( i smallint);
    >
    > Pub: insert into tab1 values(generate_series(1, 32768));
    >
    > Error on sub:
    > 2024-07-25 10:38:06.446 IST [178680] ERROR:  value "32768" is out of
    > range for type smallint
    >
    > ---------------------
    > Behaviour for sequences:
    > ---------------------
    >
    > Pub:
    > CREATE SEQUENCE myseq_i as integer INCREMENT 10000 START 1;
    >
    > Sub:
    > CREATE SEQUENCE myseq_i as smallint INCREMENT 10000 START 1;
    >
    > Pub:
    > SELECT nextval('myseq_i');
    > SELECT nextval('myseq_i');
    > SELECT nextval('myseq_i');
    > SELECT nextval('myseq_i');
    > SELECT nextval('myseq_i'); -->brings value to 40001
    >
    > Sub:
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > SELECT * from pg_sequences;  -->last_val reached till 40001, while the
    > range is till  32767.
    
    This issue is addressed in the v20240730_2 version patch attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm3%2BXzHAbgyn8gmbBLK5goyv_uyGgHEsTQxRZ8bVk6nAEg%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  96. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-31T07:25:39Z

    Hi Vignesh,
    
    Here are my review comments for your latest 0730_2* patches.
    
    Patch v20240730_2-0001 looks good to me.
    
    Patch v20240730_2-0002 looks good to me.
    
    My comments for the v20240730_2-0003 patch are below:
    
    //////////
    
    GENERAL
    
    1. Inconsistent terms
    
    I've noticed there are many variations of how the sequence sync worker is known:
    - "sequencesync worker"
    - "sequence sync worker"
    - "sequence-sync worker"
    - "sequence synchronization worker"
    - more?
    
    We must settle on some standardized name.
    
    AFAICT we generally use "table synchronization worker" in the docs,
    and "tablesync worker" in the code and comments.  IMO, we should do
    same as that for sequences -- e.g. "sequence synchronization worker"
    in the docs, and "sequencesync worker" in the code and comments.
    
    ======
    doc/src/sgml/catalogs.sgml
    
    nitpick - the links should jump directly to REFRESH PUBLICATION or
    REFRESH PUBLICATION SEQUENCES. Currently they go to the top of the
    ALTER SUBSCRIPTION page which is not as useful.
    
    ======
    src/backend/commands/sequence.c
    
    do_setval:
    nitpick - minor wording in the function header
    nitpick - change some param names to more closely resemble the fields
    they get assigned to (/logcnt/log_cnt/, /iscalled/is_called/)
    
    ~
    
    2.
      seq->is_called = iscalled;
    - seq->log_cnt = 0;
    + seq->log_cnt = (logcnt == SEQ_LOG_CNT_INVALID) ? 0: logcnt;
    
    The logic here for SEQ_LOG_CNT_INVALID seemed strange. Why not just
    #define SEQ_LOG_CNT_INVALID as 0 in the first place if that is what
    you will assign for invalid? Then you won't need to do anything here
    except seq->log_cnt = log_cnt;
    
    ======
    src/backend/catalog/pg_subscription.c
    
    HasSubscriptionRelations:
    nitpick - I think the comment "If even a single tuple exists..." is
    not quite accurate. e.g. It also has to be the right kind of tuple.
    
    ~~
    
    GetSubscriptionRelations:
    nitpick - Give more description in the function header about the other
    parameters.
    nitpick - I felt that a better name for 'all_relations' is all_states.
    Because in my mind *all relations* sounds more like when both
    'all_tables' and 'all_sequences' are true.
    nitpick - IMO add an Assert to be sure something is being fetched.
    Assert(get_tables || get_sequences);
    nitpick - Rephrase the "skip the tables" and "skip the sequences"
    comments to be more aligned with the code condition.
    
    ~
    
    3.
    - if (not_ready)
    + /* Get the relations that are not in ready state */
    + if (get_tables && !all_relations)
      ScanKeyInit(&skey[nkeys++],
      Anum_pg_subscription_rel_srsubstate,
      BTEqualStrategyNumber, F_CHARNE,
      CharGetDatum(SUBREL_STATE_READY));
    + /* Get the sequences that are in init state */
    + else if (get_sequences && !all_relations)
    + ScanKeyInit(&skey[nkeys++],
    + Anum_pg_subscription_rel_srsubstate,
    + BTEqualStrategyNumber, F_CHAREQ,
    + CharGetDatum(SUBREL_STATE_INIT));
    
    This is quite tricky, using multiple flags (get_tables and
    get_sequences) in such a way. It might even be a bug -- e.g. Is the
    'else' keyword correct? Otherwise, when both get_tables and
    get_sequences are true, and all_relations is false, then the sequence
    part wouldn't even get executed (???).
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    CreateSubscription:
    nitpick - let's move the 'tables' declaration to be beside the
    'sequences' var for consistency. (in passing move other vars too)
    nitpick - it's not strictly required for the patch, but let's change
    the 'tables' loop to be consistent with the new sequences loop.
    
    ~~~
    
    4. AlterSubscription_refresh
    
    My first impression (from the function comment) is that these function
    parameters are a bit awkward. For example,
    - It says:  If 'copy_data' parameter is true, the function will set
    the state to "init"; otherwise, it will set the state to "ready".
    - It also says: "If 'all_relations' is true, mark all objects with
    "init" state..."
    Those statements seem to clash. e.g. if copy_data is false but
    all_relations is true, then what (???)
    
    ~
    
    nitpick - tweak function comment wording.
    nitpick - introduce a 'relkind' variable to avoid multiple calls of
    get_rel_relkind(relid)
    nitpick - use an existing 'relkind' variable instead of calling
    get_rel_relkind(relid);
    nitpick - add another comment about skipping (for dropping tablesync slots)
    
    ~
    
    5.
    + /*
    + * If all the relations should be re-synchronized, then set the
    + * state to init for re-synchronization. This is currently
    + * supported only for sequences.
    + */
    + else if (all_relations)
    + {
    + ereport(DEBUG1,
    + (errmsg_internal("sequence \"%s.%s\" of subscription \"%s\" set to
    INIT state",
      get_namespace_name(get_rel_namespace(relid)),
      get_rel_name(relid),
      sub->name)));
    + UpdateSubscriptionRelState(sub->oid, relid, SUBREL_STATE_INIT,
    +    InvalidXLogRecPtr);
    
    (This is a continuation of my doubts regarding 'all_relations' in the
    previous review comment #4 above)
    
    Here are some more questions about it:
    
    ~
    
    5a. Why is this an 'else' of the !bsearch? It needs more explanation
    what this case means.
    
    ~
    
    5b. Along with more description, it might be better to reverse the
    !bsearch condition, so this ('else') code is not so distantly
    separated from the condition.
    
    ~
    
    5c. Saying "only supported for sequences" seems strange: e.g. what
    would it even mean to "re-synchronize" tables? They would all have to
    be truncated first -- so if re-sync for tables has no meaning maybe
    the parameter is misnamed and should just be 'resync_all_sequences' or
    similar? In any case, an Assert here might be good.
    
    ======
    src/backend/replication/logical/launcher.c
    
    logicalrep_worker_find:
    
    nitpick - I feel the function comment "We are only interested in..."
    is now redundant since you are passing the exact worker type you want.
    nitpick - I added an Assert for the types you are expecting to look for
    nitpick - The comment "Search for attached worker..." is stale now
    because there are more search criteria
    nitpick - IMO the "Skip parallel apply workers." code is no longer
    needed now that you are matching the worker type.
    
    ~~~
    
    6. logicalrep_worker_launch
    
      * - must be valid worker type
      * - tablesync workers are only ones to have relid
      * - parallel apply worker is the only kind of subworker
    + * - sequencesync workers will not have relid
      */
      Assert(wtype != WORKERTYPE_UNKNOWN);
      Assert(is_tablesync_worker == OidIsValid(relid));
      Assert(is_parallel_apply_worker == (subworker_dsm != DSM_HANDLE_INVALID));
    + Assert(!is_sequencesync_worker || !OidIsValid(relid));
    
    On further reflection, is that added comment and added Assert even
    needed? I think they can be removed because saying "tablesync workers
    are only ones to have relid" seems to already cover what we needed to
    say/assert.
    
    ~~~
    
    logicalrep_worker_stop:
    nitpick - /type/wtype/ for readability
    
    ~~~
    
    7.
    /*
     * Count the number of registered (not necessarily running) sync workers
     * for a subscription.
     */
    int
    logicalrep_sync_worker_count(Oid subid)
    
    ~
    
    I thought this function should count the sequencesync worker as well.
    
    ======
    .../replication/logical/sequencesync.c
    
    fetch_remote_sequence_data:
    nitpick - tweaked function comment
    nitpick - /value/last_value/ for readability
    
    ~
    
    8.
    + *lsn = DatumGetInt64(slot_getattr(slot, 4, &isnull));
    + Assert(!isnull);
    
    Should that be DatumGetUInt64?
    
    ~~~
    
    copy_sequence:
    nitpick - tweak function header.
    nitpick - renamed the sequence vars for consistency, and declared them
    all together.
    
    ======
    src/backend/replication/logical/tablesync.c
    
    9.
     void
     invalidate_syncing_table_states(Datum arg, int cacheid, uint32 hashvalue)
     {
    - table_states_validity = SYNC_TABLE_STATE_NEEDS_REBUILD;
    + relation_states_validity = SYNC_TABLE_STATE_NEEDS_REBUILD;
     }
    
    I assume you changed the 'table_states_validity' name because this is
    no longer exclusively for tables. So, should the function name also be
    similarly changed?
    
    ~~~
    
    process_syncing_sequences_for_apply:
    nitpick - tweaked the function comment
    nitpick - cannot just say "if there is not one already." a sequence
    syn worker might not even be needed.
    nitpick - added blank line for readability
    
    ~
    
    10.
    + if (syncworker)
    + {
    + /* Now safe to release the LWLock */
    + LWLockRelease(LogicalRepWorkerLock);
    + break;
    + }
    + else
    + {
    
    This 'else' can be removed if you wish to pull back all the indentation.
    
    ~~~
    
    11.
    process_syncing_tables(XLogRecPtr current_lsn)
    
    Is the function name still OK given that is is now also syncing for sequences?
    
    ~~~
    
    FetchTableStates:
    nitpick - Reworded some of the function comment
    nitpick - Function comment is stale because it is still referring to
    the function parameter which this patch removed.
    nitpick - tweak a comment
    
    ======
    src/include/commands/sequence.h
    
    12.
    +#define SEQ_LOG_CNT_INVALID (-1)
    
    See a previous review comment (#2 above) where I wondered why not use
    value 0 for this.
    
    ~~~
    
    13.
     extern void SequenceChangePersistence(Oid relid, char newrelpersistence);
     extern void DeleteSequenceTuple(Oid relid);
     extern void ResetSequence(Oid seq_relid);
    +extern void do_setval(Oid relid, int64 next, bool iscalled, int64 logcnt);
     extern void ResetSequenceCaches(void);
    
    do_setval() was an OK function name when it was static, but as an
    exposed API it seems like a terrible name. IMO rename it to something
    like 'SetSequence' to match the other API functions nearby.
    
    ~
    
    nitpick - same change to the parameter names as suggested for the
    implementation.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  97. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-07-31T09:08:46Z

    On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    > >
    > >
    > >
    > > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    > >>
    > >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >> [...]
    > >> A new catalog table, pg_subscription_seq, has been introduced for
    > >> mapping subscriptions to sequences. Additionally, the sequence LSN
    > >> (Log Sequence Number) is stored, facilitating determination of
    > >> sequence changes occurring before or after the returned sequence
    > >> state.
    > >
    > >
    > > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    > > something.
    >
    > We'll require the lsn because the sequence LSN informs the user that
    > it has been synchronized up to the LSN in pg_subscription_seq. Since
    > we are not supporting incremental sync, the user will be able to
    > identify if he should run refresh sequences or not by checking the lsn
    > of the pg_subscription_seq and the lsn of the sequence(using
    > pg_sequence_state added) in the publisher.
    
    How the user will know from seq's lsn that he needs to run refresh.
    lsn indicates page_lsn and thus the sequence might advance on pub
    without changing lsn and thus lsn may look the same on subscriber even
    though a sequence-refresh is needed. Am I missing something here?
    
    thanks
    Shveta
    
    
    
    
  98. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-07-31T09:33:15Z

    On Sat, 20 Jul 2024 at 20:48, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 12 Jul 2024 at 08:22, Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > Hi Vignesh. Here are the rest of my comments for patch v20240705-0003.
    > > ======
    > >
    > > 8. logicalrep_sequence_sync_worker_find
    > >
    > > +/*
    > > + * Walks the workers array and searches for one that matches given
    > > + * subscription id.
    > > + *
    > > + * We are only interested in the sequence sync worker.
    > > + */
    > > +LogicalRepWorker *
    > > +logicalrep_sequence_sync_worker_find(Oid subid, bool only_running)
    > >
    > > There are other similar functions for walking the workers array to
    > > search for a worker. Instead of having different functions for
    > > different cases, wouldn't it be cleaner to combine these into a single
    > > function, where you pass a parameter (e.g. a mask of worker types that
    > > you are interested in finding)?
    
    This is fixed in the v20240730_2 version attached at [1].
    
    > > 17.
    > > Also, where does the number 100 come from? Why not 1000? Why not 10?
    > > Why have batching at all? Maybe there should be some comment to
    > > describe the reason and the chosen value.
    
    I had run some tests with 10/100 and 1000 sequences per batch for
    10000 sequences. The results for it:
    10 per batch   - 4.94 seconds
    100 per batch  - 4.87 seconds
    1000 per batch - 4.53 seconds
    
    There is not much time difference between each of them. Currently, it
    is set to 100, which seems fine since it will not generate a lot of
    transactions. Additionally, the locks on the sequences will be
    periodically released during the commit transaction.
    
    I had used the test from the attached patch by changing
    max_sequences_sync_per_batch to 10/100/100 in 035_sequences.pl to
    verify this.
    
    [1] - https://www.postgresql.org/message-id/CALDaNm3%2BXzHAbgyn8gmbBLK5goyv_uyGgHEsTQxRZ8bVk6nAEg%40mail.gmail.com
    
    Regards,
    Vignesh
    
  99. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-31T22:27:38Z

    Hi Vignesh,
    
    I have a question about the subscriber-side behaviour of currval().
    
    ======
    
    AFAIK it is normal for currval() to give error is nextval() has not
    yet been called [1]
    
    For example.
    test_pub=# create sequence s1;
    CREATE SEQUENCE
    test_pub=# select * from currval('s1');
    2024-08-01 07:42:48.619 AEST [24131] ERROR:  currval of sequence "s1"
    is not yet defined in this session
    2024-08-01 07:42:48.619 AEST [24131] STATEMENT:  select * from currval('s1');
    ERROR:  currval of sequence "s1" is not yet defined in this session
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           1
    (1 row)
    
    test_pub=# select * from currval('s1');
     currval
    ---------
           1
    (1 row)
    
    test_pub=#
    
    ~~~
    
    OTOH, I was hoping to be able to use currval() at the subscriber=side
    to see the current sequence value after issuing ALTER .. REFRESH
    PUBLICATION SEQUENCES.
    
    Unfortunately, it has the same behaviour where currval() cannot be
    used without nextval(). But, on the subscriber, you probably never
    want to do an explicit nextval() independently of the publisher.
    
    Is this currently a bug, or maybe a quirk that should be documented?
    
    For example:
    
    Publisher
    ==========
    
    test_pub=# create sequence s1;
    CREATE SEQUENCE
    test_pub=# CREATE PUBLICATION pub1 FOR ALL SEQUENCES;
    CREATE PUBLICATION
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           1
    (1 row)
    
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           2
    (1 row)
    
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           3
    (1 row)
    
    test_pub=#
    
    Subscriber
    ==========
    
    (Notice currval() always gives an error unless nextval() is used prior).
    
    test_sub=# create sequence s1;
    CREATE SEQUENCE
    test_sub=# CREATE SUBSCRIPTION sub1 CONNECTION 'dbname=test_pub'
    PUBLICATION pub1;
    2024-08-01 07:51:06.955 AEST [24325] WARNING:  subscriptions created
    by regression test cases should have names starting with "regress_"
    WARNING:  subscriptions created by regression test cases should have
    names starting with "regress_"
    NOTICE:  created replication slot "sub1" on publisher
    CREATE SUBSCRIPTION
    test_sub=# 2024-08-01 07:51:07.023 AEST [4211] LOG:  logical
    replication apply worker for subscription "sub1" has started
    2024-08-01 07:51:07.037 AEST [4213] LOG:  logical replication sequence
    synchronization worker for subscription "sub1" has started
    2024-08-01 07:51:07.063 AEST [4213] LOG:  logical replication
    synchronization for subscription "sub1", sequence "s1" has finished
    2024-08-01 07:51:07.063 AEST [4213] LOG:  logical replication sequence
    synchronization worker for subscription "sub1" has finished
    
    test_sub=# SELECT * FROM currval('s1');
    2024-08-01 07:51:19.688 AEST [24325] ERROR:  currval of sequence "s1"
    is not yet defined in this session
    2024-08-01 07:51:19.688 AEST [24325] STATEMENT:  SELECT * FROM currval('s1');
    ERROR:  currval of sequence "s1" is not yet defined in this session
    test_sub=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    ALTER SUBSCRIPTION
    test_sub=# 2024-08-01 07:51:35.298 AEST [4993] LOG:  logical
    replication sequence synchronization worker for subscription "sub1"
    has started
    
    test_sub=# 2024-08-01 07:51:35.321 AEST [4993] LOG:  logical
    replication synchronization for subscription "sub1", sequence "s1" has
    finished
    2024-08-01 07:51:35.321 AEST [4993] LOG:  logical replication sequence
    synchronization worker for subscription "sub1" has finished
    
    test_sub=#
    test_sub=# SELECT * FROM currval('s1');
    2024-08-01 07:51:41.438 AEST [24325] ERROR:  currval of sequence "s1"
    is not yet defined in this session
    2024-08-01 07:51:41.438 AEST [24325] STATEMENT:  SELECT * FROM currval('s1');
    ERROR:  currval of sequence "s1" is not yet defined in this session
    test_sub=#
    test_sub=# SELECT * FROM nextval('s1');
     nextval
    ---------
           4
    (1 row)
    
    test_sub=# SELECT * FROM currval('s1');
     currval
    ---------
           4
    (1 row)
    
    test_sub=#
    
    ======
    [1] https://www.postgresql.org/docs/current/functions-sequence.html
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia.
    
    
    
    
  100. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-07-31T22:55:13Z

    Hi Vignesh,
    
    I noticed that when replicating sequences (using the latest patches
    0730_2*)  the subscriber-side checks the *existence* of the sequence,
    but apparently it is not checking other sequence attributes.
    
    For example, consider:
    
    Publisher: "CREATE SEQUENCE s1 START 1 INCREMENT 2;" should be a
    sequence of only odd numbers.
    Subscriber: "CREATE SEQUENCE s1 START 2 INCREMENT 2;" should be a
    sequence of only even numbers.
    
    Because the names match, currently the patch allows replication of the
    s1 sequence. I think that might lead to unexpected results on the
    subscriber. IMO it might be safer to report ERROR unless the sequences
    match properly (i.e. not just a name check).
    
    Below is a demonstration the problem:
    
    ==========
    Publisher:
    ==========
    
    (publisher sequence is odd numbers)
    
    test_pub=# create sequence s1 start 1 increment 2;
    CREATE SEQUENCE
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           1
    (1 row)
    
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           3
    (1 row)
    
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           5
    (1 row)
    
    test_pub=# CREATE PUBLICATION pub1 FOR ALL SEQUENCES;
    CREATE PUBLICATION
    test_pub=#
    
    ==========
    Subscriber:
    ==========
    
    (subscriber sequence is even numbers)
    
    test_sub=# create sequence s1 start 2 increment 2;
    CREATE SEQUENCE
    test_sub=# SELECT * FROM nextval('s1');
     nextval
    ---------
           2
    (1 row)
    
    test_sub=# SELECT * FROM nextval('s1');
     nextval
    ---------
           4
    (1 row)
    
    test_sub=# SELECT * FROM nextval('s1');
     nextval
    ---------
           6
    (1 row)
    
    test_sub=# CREATE SUBSCRIPTION sub1 CONNECTION 'dbname=test_pub'
    PUBLICATION pub1;
    2024-08-01 08:43:04.198 AEST [24325] WARNING:  subscriptions created
    by regression test cases should have names starting with "regress_"
    WARNING:  subscriptions created by regression test cases should have
    names starting with "regress_"
    NOTICE:  created replication slot "sub1" on publisher
    CREATE SUBSCRIPTION
    test_sub=# 2024-08-01 08:43:04.294 AEST [26240] LOG:  logical
    replication apply worker for subscription "sub1" has started
    2024-08-01 08:43:04.309 AEST [26244] LOG:  logical replication
    sequence synchronization worker for subscription "sub1" has started
    2024-08-01 08:43:04.323 AEST [26244] LOG:  logical replication
    synchronization for subscription "sub1", sequence "s1" has finished
    2024-08-01 08:43:04.323 AEST [26244] LOG:  logical replication
    sequence synchronization worker for subscription "sub1" has finished
    
    (after the CREATE SUBSCRIPTION we are getting replicated odd values
    from the publisher, even though the subscriber side sequence was
    supposed to be even numbers)
    
    test_sub=# SELECT * FROM nextval('s1');
     nextval
    ---------
           7
    (1 row)
    
    test_sub=# SELECT * FROM nextval('s1');
     nextval
    ---------
           9
    (1 row)
    
    test_sub=# SELECT * FROM nextval('s1');
     nextval
    ---------
          11
    (1 row)
    
    (Looking at the description you would expect odd values for this
    sequence to be impossible)
    
    test_sub=# \dS+ s1
                                 Sequence "public.s1"
      Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache
    --------+-------+---------+---------------------+-----------+---------+-------
     bigint |     2 |       1 | 9223372036854775807 |         2 | no      |     1
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  101. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-08-02T08:54:45Z

    On Thu, Aug 1, 2024 at 9:26 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Mon, Jul 29, 2024 at 4:17 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > Thanks for reporting this, these issues are fixed in the attached
    > > v20240730_2 version patch.
    > >
    
    I was reviewing the design of patch003, and I have a query. Do we need
    to even start an apply worker and create replication slot when
    subscription created is for 'sequences only'? IIUC, currently logical
    replication apply worker is the one launching sequence-sync worker
    whenever needed. I think it should be the launcher doing this job and
    thus apply worker may even not be needed for current functionality of
    sequence sync? Going forward when we implement incremental sync of
    sequences, then we may have apply worker started but now it is not
    needed.
    
    thanks
    Shveta
    
    
    
    
  102. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-08-02T09:03:32Z

    On Fri, Aug 2, 2024 at 2:24 PM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Thu, Aug 1, 2024 at 9:26 AM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Mon, Jul 29, 2024 at 4:17 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > Thanks for reporting this, these issues are fixed in the attached
    > > > v20240730_2 version patch.
    > > >
    >
    > I was reviewing the design of patch003, and I have a query. Do we need
    > to even start an apply worker and create replication slot when
    > subscription created is for 'sequences only'? IIUC, currently logical
    > replication apply worker is the one launching sequence-sync worker
    > whenever needed. I think it should be the launcher doing this job and
    > thus apply worker may even not be needed for current functionality of
    > sequence sync? Going forward when we implement incremental sync of
    > sequences, then we may have apply worker started but now it is not
    > needed.
    >
    
    Also, can we please mention the state change and 'who does what' atop
    sequencesync.c file similar to what we have atop tablesync.c file
    otherwise it is difficult to figure out the flow.
    
    thanks
    Shveta
    
    
    
    
  103. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-05T04:29:54Z

    On Wed, 31 Jul 2024 at 12:56, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Here are my review comments for your latest 0730_2* patches.
    >
    > Patch v20240730_2-0001 looks good to me.
    >
    > Patch v20240730_2-0002 looks good to me.
    >
    > My comments for the v20240730_2-0003 patch are below:
    > ~~~
    >
    > 4. AlterSubscription_refresh
    >
    > My first impression (from the function comment) is that these function
    > parameters are a bit awkward. For example,
    > - It says:  If 'copy_data' parameter is true, the function will set
    > the state to "init"; otherwise, it will set the state to "ready".
    > - It also says: "If 'all_relations' is true, mark all objects with
    > "init" state..."
    > Those statements seem to clash. e.g. if copy_data is false but
    > all_relations is true, then what (???)
    
    all_relations will be true only for "ALTER SUBSCRIPTION ... REFRESH
    PUBLICATION SEQUENCES".  With option is not supported along with this
    command so copy_data with false option is not possible here. Added an
    assert for this.
    >
    > 8.
    > + *lsn = DatumGetInt64(slot_getattr(slot, 4, &isnull));
    > + Assert(!isnull);
    >
    > Should that be DatumGetUInt64?
    
    It should be DatumGetLSN here.
    
    The rest of the comments are fixed. The attached v20240805 version
    patch has the changes for the same.
    
    Regards,
    Vignesh
    
  104. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-05T04:44:03Z

    On Thu, 1 Aug 2024 at 03:33, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > I have a question about the subscriber-side behaviour of currval().
    >
    > ======
    >
    > AFAIK it is normal for currval() to give error is nextval() has not
    > yet been called [1]
    >
    > For example.
    > test_pub=# create sequence s1;
    > CREATE SEQUENCE
    > test_pub=# select * from currval('s1');
    > 2024-08-01 07:42:48.619 AEST [24131] ERROR:  currval of sequence "s1"
    > is not yet defined in this session
    > 2024-08-01 07:42:48.619 AEST [24131] STATEMENT:  select * from currval('s1');
    > ERROR:  currval of sequence "s1" is not yet defined in this session
    > test_pub=# select * from nextval('s1');
    >  nextval
    > ---------
    >        1
    > (1 row)
    >
    > test_pub=# select * from currval('s1');
    >  currval
    > ---------
    >        1
    > (1 row)
    >
    > test_pub=#
    >
    > ~~~
    >
    > OTOH, I was hoping to be able to use currval() at the subscriber=side
    > to see the current sequence value after issuing ALTER .. REFRESH
    > PUBLICATION SEQUENCES.
    >
    > Unfortunately, it has the same behaviour where currval() cannot be
    > used without nextval(). But, on the subscriber, you probably never
    > want to do an explicit nextval() independently of the publisher.
    >
    > Is this currently a bug, or maybe a quirk that should be documented?
    
    The currval returns the most recent value obtained from the nextval
    function for a given sequence within the current session. This
    function is specific to the session, meaning it only provides the last
    sequence value retrieved during that session. However, if you call
    currval before using nextval in the same session, you'll encounter an
    error stating "currval of the sequence is not yet defined in this
    session." Meaning even in the publisher this value is only visible in
    the current session and not in a different session. Alternatively you
    can use the following to get the last_value of the sequence: SELECT
    last_value FROM sequence_name. I feel this need not be documented as
    the similar issue is present in the publisher and there is an "SELECT
    last_value FROM sequence_name" to get the last_value.
    
    Regards,
    Vignesh
    
    
    
    
  105. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-05T04:56:38Z

    On Thu, 1 Aug 2024 at 04:25, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > I noticed that when replicating sequences (using the latest patches
    > 0730_2*)  the subscriber-side checks the *existence* of the sequence,
    > but apparently it is not checking other sequence attributes.
    >
    > For example, consider:
    >
    > Publisher: "CREATE SEQUENCE s1 START 1 INCREMENT 2;" should be a
    > sequence of only odd numbers.
    > Subscriber: "CREATE SEQUENCE s1 START 2 INCREMENT 2;" should be a
    > sequence of only even numbers.
    >
    > Because the names match, currently the patch allows replication of the
    > s1 sequence. I think that might lead to unexpected results on the
    > subscriber. IMO it might be safer to report ERROR unless the sequences
    > match properly (i.e. not just a name check).
    >
    > Below is a demonstration the problem:
    >
    > ==========
    > Publisher:
    > ==========
    >
    > (publisher sequence is odd numbers)
    >
    > test_pub=# create sequence s1 start 1 increment 2;
    > CREATE SEQUENCE
    > test_pub=# select * from nextval('s1');
    >  nextval
    > ---------
    >        1
    > (1 row)
    >
    > test_pub=# select * from nextval('s1');
    >  nextval
    > ---------
    >        3
    > (1 row)
    >
    > test_pub=# select * from nextval('s1');
    >  nextval
    > ---------
    >        5
    > (1 row)
    >
    > test_pub=# CREATE PUBLICATION pub1 FOR ALL SEQUENCES;
    > CREATE PUBLICATION
    > test_pub=#
    >
    > ==========
    > Subscriber:
    > ==========
    >
    > (subscriber sequence is even numbers)
    >
    > test_sub=# create sequence s1 start 2 increment 2;
    > CREATE SEQUENCE
    > test_sub=# SELECT * FROM nextval('s1');
    >  nextval
    > ---------
    >        2
    > (1 row)
    >
    > test_sub=# SELECT * FROM nextval('s1');
    >  nextval
    > ---------
    >        4
    > (1 row)
    >
    > test_sub=# SELECT * FROM nextval('s1');
    >  nextval
    > ---------
    >        6
    > (1 row)
    >
    > test_sub=# CREATE SUBSCRIPTION sub1 CONNECTION 'dbname=test_pub'
    > PUBLICATION pub1;
    > 2024-08-01 08:43:04.198 AEST [24325] WARNING:  subscriptions created
    > by regression test cases should have names starting with "regress_"
    > WARNING:  subscriptions created by regression test cases should have
    > names starting with "regress_"
    > NOTICE:  created replication slot "sub1" on publisher
    > CREATE SUBSCRIPTION
    > test_sub=# 2024-08-01 08:43:04.294 AEST [26240] LOG:  logical
    > replication apply worker for subscription "sub1" has started
    > 2024-08-01 08:43:04.309 AEST [26244] LOG:  logical replication
    > sequence synchronization worker for subscription "sub1" has started
    > 2024-08-01 08:43:04.323 AEST [26244] LOG:  logical replication
    > synchronization for subscription "sub1", sequence "s1" has finished
    > 2024-08-01 08:43:04.323 AEST [26244] LOG:  logical replication
    > sequence synchronization worker for subscription "sub1" has finished
    >
    > (after the CREATE SUBSCRIPTION we are getting replicated odd values
    > from the publisher, even though the subscriber side sequence was
    > supposed to be even numbers)
    >
    > test_sub=# SELECT * FROM nextval('s1');
    >  nextval
    > ---------
    >        7
    > (1 row)
    >
    > test_sub=# SELECT * FROM nextval('s1');
    >  nextval
    > ---------
    >        9
    > (1 row)
    >
    > test_sub=# SELECT * FROM nextval('s1');
    >  nextval
    > ---------
    >       11
    > (1 row)
    >
    > (Looking at the description you would expect odd values for this
    > sequence to be impossible)
    >
    > test_sub=# \dS+ s1
    >                              Sequence "public.s1"
    >   Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache
    > --------+-------+---------+---------------------+-----------+---------+-------
    >  bigint |     2 |       1 | 9223372036854775807 |         2 | no      |     1
    
    Even if we check the sequence definition during the CREATE
    SUBSCRIPTION/ALTER SUBSCRIPTION ... REFRESH PUBLICATION or ALTER
    SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES commands, there's still
    a chance that the sequence definition might change after the command
    has been executed. Currently, there's no mechanism to lock a sequence,
    and we also permit replication of table data even if the table
    structures differ, such as mismatched data types like int and
    smallint. I have modified it to log a warning to inform users that the
    sequence options on the publisher and subscriber are not the same and
    advise them to ensure that the sequence definitions are consistent
    between both.
    The v20240805 version patch attached at [1] has the changes for the same.
    [1] - https://www.postgresql.org/message-id/CALDaNm1Y_ot-jFRfmtwDuwmFrgSSYHjVuy28RspSopTtwzXy8w%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  106. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-05T05:34:31Z

    On Wed, 31 Jul 2024 at 14:39, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    > > >
    > > >
    > > >
    > > > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >>
    > > >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >> [...]
    > > >> A new catalog table, pg_subscription_seq, has been introduced for
    > > >> mapping subscriptions to sequences. Additionally, the sequence LSN
    > > >> (Log Sequence Number) is stored, facilitating determination of
    > > >> sequence changes occurring before or after the returned sequence
    > > >> state.
    > > >
    > > >
    > > > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    > > > something.
    > >
    > > We'll require the lsn because the sequence LSN informs the user that
    > > it has been synchronized up to the LSN in pg_subscription_seq. Since
    > > we are not supporting incremental sync, the user will be able to
    > > identify if he should run refresh sequences or not by checking the lsn
    > > of the pg_subscription_seq and the lsn of the sequence(using
    > > pg_sequence_state added) in the publisher.
    >
    > How the user will know from seq's lsn that he needs to run refresh.
    > lsn indicates page_lsn and thus the sequence might advance on pub
    > without changing lsn and thus lsn may look the same on subscriber even
    > though a sequence-refresh is needed. Am I missing something here?
    
    When a sequence is synchronized to the subscriber, the page LSN of the
    sequence from the publisher is also retrieved and stored in
    pg_subscriber_rel as shown below:
    --- Publisher page lsn
    publisher=# select pg_sequence_state('seq1');
     pg_sequence_state
    --------------------
     (0/1510E38,65,1,t)
    (1 row)
    
    --- Subscriber stores the publisher's page lsn for the sequence
    subscriber=# select * from pg_subscription_rel where srrelid = 16384;
     srsubid | srrelid | srsubstate | srsublsn
    ---------+---------+------------+-----------
       16389 |   16384 | r          | 0/1510E38
    (1 row)
    
    If changes are made to the sequence, such as performing many nextvals,
    the page LSN will be updated. Currently the sequence values are
    prefetched for SEQ_LOG_VALS 32, so the lsn will not get updated for
    the prefetched values, once the prefetched values are consumed the lsn
    will get updated.
    For example:
    --- Updated LSN on the publisher (old lsn - 0/1510E38, new lsn - 0/1558CA8)
    publisher=# select pg_sequence_state('seq1');
      pg_sequence_state
    ----------------------
     (0/1558CA8,143,22,t)
    (1 row)
    
    The user can then compare this updated value with the sequence's LSN
    in pg_subscription_rel to determine when to re-synchronize the
    sequence.
    
    Regards,
    Vignesh
    
    
    
    
  107. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-05T09:04:34Z

    On Thu, 1 Aug 2024 at 09:26, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Mon, Jul 29, 2024 at 4:17 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > Thanks for reporting this, these issues are fixed in the attached
    > > v20240730_2 version patch.
    > >
    >
    > Thanks for addressing the comments. Please find few comments on patch001 alone:
    >
    > Potential Bug:
    > 1) 'last_value' returned by pg_sequence_state() is wrong initially.
    >
    > postgres=# create sequence myseq5;
    > CREATE SEQUENCE
    >
    > postgres=# select * from pg_sequence_state('myseq5');
    >  page_lsn  | last_value | log_cnt | is_called
    > -----------+------------+---------+-----------
    >  0/1579C78 |          1 |       0 | f
    >
    > postgres=# SELECT nextval('myseq5') ;
    >  nextval
    > ---------
    >        1
    >
    > postgres=# select * from pg_sequence_state('myseq5');
    >  page_lsn  | last_value | log_cnt | is_called
    > -----------+------------+---------+-----------
    >  0/1579FD8 |          1 |      32 | t
    >
    >
    > Both calls returned 1. First call should have returned NULL.
    
    I noticed the same behavior for selecting from a sequence:
    postgres=# select * from myseq5;
     last_value | log_cnt | is_called
    ------------+---------+-----------
              1 |       0 | f
    (1 row)
    
    postgres=# select nextval('myseq5');
     nextval
    ---------
           1
    (1 row)
    
    postgres=# select * from myseq5;
     last_value | log_cnt | is_called
    ------------+---------+-----------
              1 |      32 | t
    (1 row)
    
    By default it shows the last_value as the start value for the
    sequence. So this looks ok to me.
    
    > 2)
    > func.sgml:
    > a) pg_sequence_state : Don't we need to give input arg as regclass
    > like we give in  nextval,setval etc?
    > b) Should 'lsn' be changed to 'page_lsn' as returned in output of
    > pg_sequence_state()
    
    Modified
    
    >
    > 3)
    > read_seq_tuple() header says:
    >  * lsn_ret will be set to the page LSN if the caller requested it.
    >  * This allows the caller to determine which sequence changes are
    >  * before/after the returned sequence state.
    >
    > How, using lsn which is page-lsn and not sequence value/change lsn,
    > does the user interpret if sequence changes are before/after the
    > returned sequence state? Can you please elaborate or amend the
    > comment?
    
    I have added this to pg_sequence_state function header in 003 patch as
    the subscriber side changes are present here, I felt that is more apt
    to mention. This is also added in sequencesync.c file header.
    
    The attached v20240805_2 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  108. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-05T09:06:37Z

    On Fri, 2 Aug 2024 at 14:24, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Thu, Aug 1, 2024 at 9:26 AM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Mon, Jul 29, 2024 at 4:17 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > Thanks for reporting this, these issues are fixed in the attached
    > > > v20240730_2 version patch.
    > > >
    >
    > I was reviewing the design of patch003, and I have a query. Do we need
    > to even start an apply worker and create replication slot when
    > subscription created is for 'sequences only'? IIUC, currently logical
    > replication apply worker is the one launching sequence-sync worker
    > whenever needed. I think it should be the launcher doing this job and
    > thus apply worker may even not be needed for current functionality of
    > sequence sync? Going forward when we implement incremental sync of
    > sequences, then we may have apply worker started but now it is not
    > needed.
    
    I believe the current method of having the apply worker initiate the
    sequence sync worker is advantageous for several reasons:
    a) Reduces Launcher Load: This approach prevents overloading the
    launcher, which must handle various other subscription requests.
    b) Facilitates Incremental Sync: It provides a more straightforward
    path to extend support for incremental sequence synchronization.
    c) Reuses Existing Code: It leverages the existing tablesync worker
    code for starting the tablesync process, avoiding the need to
    duplicate code in the launcher.
    d) Simplified Code Maintenance: Centralizing sequence synchronization
    logic within the apply worker can simplify code maintenance and
    updates, as changes will only need to be made in one place rather than
    across multiple components.
    e) Better Monitoring and Debugging: With sequence synchronization
    being handled by the apply worker, you can more effectively monitor
    and debug synchronization processes since all related operations are
    managed by a single component.
    
    Also, I noticed that even when a publication has no tables, we create
    replication slot and start apply worker.
    
    Regards,
    Vignesh
    
    
    
    
  109. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-05T09:09:44Z

    On Fri, 2 Aug 2024 at 14:33, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Fri, Aug 2, 2024 at 2:24 PM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Thu, Aug 1, 2024 at 9:26 AM shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > > > On Mon, Jul 29, 2024 at 4:17 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > Thanks for reporting this, these issues are fixed in the attached
    > > > > v20240730_2 version patch.
    > > > >
    > >
    > > I was reviewing the design of patch003, and I have a query. Do we need
    > > to even start an apply worker and create replication slot when
    > > subscription created is for 'sequences only'? IIUC, currently logical
    > > replication apply worker is the one launching sequence-sync worker
    > > whenever needed. I think it should be the launcher doing this job and
    > > thus apply worker may even not be needed for current functionality of
    > > sequence sync? Going forward when we implement incremental sync of
    > > sequences, then we may have apply worker started but now it is not
    > > needed.
    > >
    >
    > Also, can we please mention the state change and 'who does what' atop
    > sequencesync.c file similar to what we have atop tablesync.c file
    > otherwise it is difficult to figure out the flow.
    
    I have added this in sequencesync.c file, the changes for the same are
    available at v20240805_2 version patch at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm1kk1MHGk3BU_XTxay%3DdR6sMHnm4TT5cmVz2f_JXkWENQ%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  110. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-08-05T11:57:55Z

    On Mon, Aug 5, 2024 at 2:36 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 2 Aug 2024 at 14:24, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Thu, Aug 1, 2024 at 9:26 AM shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > > > On Mon, Jul 29, 2024 at 4:17 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > Thanks for reporting this, these issues are fixed in the attached
    > > > > v20240730_2 version patch.
    > > > >
    > >
    > > I was reviewing the design of patch003, and I have a query. Do we need
    > > to even start an apply worker and create replication slot when
    > > subscription created is for 'sequences only'? IIUC, currently logical
    > > replication apply worker is the one launching sequence-sync worker
    > > whenever needed. I think it should be the launcher doing this job and
    > > thus apply worker may even not be needed for current functionality of
    > > sequence sync?
    >
    
    But that would lead to maintaining all sequence-sync of each
    subscription by launcher. Say there are 100 sequences per subscription
    and some of them from each subscription are failing due to some
    reasons then the launcher will be responsible for ensuring all the
    sequences are synced. I think it would be better to handle
    per-subscription work by the apply worker.
    
    >
    > Going forward when we implement incremental sync of
    > > sequences, then we may have apply worker started but now it is not
    > > needed.
    >
    > I believe the current method of having the apply worker initiate the
    > sequence sync worker is advantageous for several reasons:
    > a) Reduces Launcher Load: This approach prevents overloading the
    > launcher, which must handle various other subscription requests.
    > b) Facilitates Incremental Sync: It provides a more straightforward
    > path to extend support for incremental sequence synchronization.
    > c) Reuses Existing Code: It leverages the existing tablesync worker
    > code for starting the tablesync process, avoiding the need to
    > duplicate code in the launcher.
    > d) Simplified Code Maintenance: Centralizing sequence synchronization
    > logic within the apply worker can simplify code maintenance and
    > updates, as changes will only need to be made in one place rather than
    > across multiple components.
    > e) Better Monitoring and Debugging: With sequence synchronization
    > being handled by the apply worker, you can more effectively monitor
    > and debug synchronization processes since all related operations are
    > managed by a single component.
    >
    > Also, I noticed that even when a publication has no tables, we create
    > replication slot and start apply worker.
    >
    
    As far as I understand slots and origins are primarily required for
    incremental sync. Would it be used only for sequence-sync cases? If
    not then we can avoid creating those. I agree that it would add some
    complexity to the code with sequence-specific checks, so we can create
    a top-up patch for this if required and evaluate its complexity versus
    the benefit it produces.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  111. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-08-05T12:35:13Z

    On Mon, Aug 5, 2024 at 11:04 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 31 Jul 2024 at 14:39, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    > > > >
    > > > >
    > > > >
    > > > > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >>
    > > > >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >> [...]
    > > > >> A new catalog table, pg_subscription_seq, has been introduced for
    > > > >> mapping subscriptions to sequences. Additionally, the sequence LSN
    > > > >> (Log Sequence Number) is stored, facilitating determination of
    > > > >> sequence changes occurring before or after the returned sequence
    > > > >> state.
    > > > >
    > > > >
    > > > > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    > > > > something.
    > > >
    > > > We'll require the lsn because the sequence LSN informs the user that
    > > > it has been synchronized up to the LSN in pg_subscription_seq. Since
    > > > we are not supporting incremental sync, the user will be able to
    > > > identify if he should run refresh sequences or not by checking the lsn
    > > > of the pg_subscription_seq and the lsn of the sequence(using
    > > > pg_sequence_state added) in the publisher.
    > >
    > > How the user will know from seq's lsn that he needs to run refresh.
    > > lsn indicates page_lsn and thus the sequence might advance on pub
    > > without changing lsn and thus lsn may look the same on subscriber even
    > > though a sequence-refresh is needed. Am I missing something here?
    >
    > When a sequence is synchronized to the subscriber, the page LSN of the
    > sequence from the publisher is also retrieved and stored in
    > pg_subscriber_rel as shown below:
    > --- Publisher page lsn
    > publisher=# select pg_sequence_state('seq1');
    >  pg_sequence_state
    > --------------------
    >  (0/1510E38,65,1,t)
    > (1 row)
    >
    > --- Subscriber stores the publisher's page lsn for the sequence
    > subscriber=# select * from pg_subscription_rel where srrelid = 16384;
    >  srsubid | srrelid | srsubstate | srsublsn
    > ---------+---------+------------+-----------
    >    16389 |   16384 | r          | 0/1510E38
    > (1 row)
    >
    > If changes are made to the sequence, such as performing many nextvals,
    > the page LSN will be updated. Currently the sequence values are
    > prefetched for SEQ_LOG_VALS 32, so the lsn will not get updated for
    > the prefetched values, once the prefetched values are consumed the lsn
    > will get updated.
    > For example:
    > --- Updated LSN on the publisher (old lsn - 0/1510E38, new lsn - 0/1558CA8)
    > publisher=# select pg_sequence_state('seq1');
    >   pg_sequence_state
    > ----------------------
    >  (0/1558CA8,143,22,t)
    > (1 row)
    >
    > The user can then compare this updated value with the sequence's LSN
    > in pg_subscription_rel to determine when to re-synchronize the
    > sequence.
    
    Thanks for the details. But I was referring to the case where we are
    in between pre-fetched values on publisher (say at 25th value), while
    on subscriber we are slightly behind (say at 15th value), but page-lsn
    will be the same on both. Since the subscriber is behind, a
    sequence-refresh is needed on sub, but by looking at lsn (which is
    same), one can not say that for sure.  Let me know if I have
    misunderstood it.
    
    thanks
    Shveta
    
    
    
    
  112. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-08-06T03:19:23Z

    On Mon, Aug 5, 2024 at 5:28 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Mon, Aug 5, 2024 at 2:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Fri, 2 Aug 2024 at 14:24, shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > > > On Thu, Aug 1, 2024 at 9:26 AM shveta malik <shveta.malik@gmail.com> wrote:
    > > > >
    > > > > On Mon, Jul 29, 2024 at 4:17 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > >
    > > > > > Thanks for reporting this, these issues are fixed in the attached
    > > > > > v20240730_2 version patch.
    > > > > >
    > > >
    > > > I was reviewing the design of patch003, and I have a query. Do we need
    > > > to even start an apply worker and create replication slot when
    > > > subscription created is for 'sequences only'? IIUC, currently logical
    > > > replication apply worker is the one launching sequence-sync worker
    > > > whenever needed. I think it should be the launcher doing this job and
    > > > thus apply worker may even not be needed for current functionality of
    > > > sequence sync?
    > >
    >
    > But that would lead to maintaining all sequence-sync of each
    > subscription by launcher. Say there are 100 sequences per subscription
    > and some of them from each subscription are failing due to some
    > reasons then the launcher will be responsible for ensuring all the
    > sequences are synced. I think it would be better to handle
    > per-subscription work by the apply worker.
    
    I thought we can give that task to sequence-sync worker. Once sequence
    sync worker is started by launcher, it keeps on syncing until all the
    sequences are synced (even failed ones) and then exits only after all
    are synced; instead of apply worker starting it multiple times for
    failed sequences. Launcher to start sequence sync worker when signaled
    by 'alter-sub refresh seq'.
    But after going through details given by Vignesh in [1], I also see
    the benefits of using apply worker for this task. Since apply worker
    is already looping and doing that for table-sync, we can reuse the
    same code for sequence sync and maintenance will be easy. So looks
    okay if we go with existing apply worker design.
    
    [1]: https://www.postgresql.org/message-id/CALDaNm1KO8f3Fj%2BRHHXM%3DUSGwOcW242M1jHee%3DX_chn2ToiCpw%40mail.gmail.com
    
    >
    > >
    > > Going forward when we implement incremental sync of
    > > > sequences, then we may have apply worker started but now it is not
    > > > needed.
    > >
    > > I believe the current method of having the apply worker initiate the
    > > sequence sync worker is advantageous for several reasons:
    > > a) Reduces Launcher Load: This approach prevents overloading the
    > > launcher, which must handle various other subscription requests.
    > > b) Facilitates Incremental Sync: It provides a more straightforward
    > > path to extend support for incremental sequence synchronization.
    > > c) Reuses Existing Code: It leverages the existing tablesync worker
    > > code for starting the tablesync process, avoiding the need to
    > > duplicate code in the launcher.
    > > d) Simplified Code Maintenance: Centralizing sequence synchronization
    > > logic within the apply worker can simplify code maintenance and
    > > updates, as changes will only need to be made in one place rather than
    > > across multiple components.
    > > e) Better Monitoring and Debugging: With sequence synchronization
    > > being handled by the apply worker, you can more effectively monitor
    > > and debug synchronization processes since all related operations are
    > > managed by a single component.
    > >
    > > Also, I noticed that even when a publication has no tables, we create
    > > replication slot and start apply worker.
    > >
    >
    > As far as I understand slots and origins are primarily required for
    > incremental sync. Would it be used only for sequence-sync cases? If
    > not then we can avoid creating those. I agree that it would add some
    > complexity to the code with sequence-specific checks, so we can create
    > a top-up patch for this if required and evaluate its complexity versus
    > the benefit it produces.
    >
    > --
    > With Regards,
    > Amit Kapila.
    
    
    
    
  113. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-08-06T03:58:34Z

    On Tue, Aug 6, 2024 at 8:49 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    
    Do we need some kind of coordination between table sync and sequence
    sync for internally generated sequences? Lets say we have an identity
    column with a 'GENERATED ALWAYS' sequence. When the sequence is synced
    to subscriber, subscriber can also do an insert to table (extra one)
    incrementing the sequence and then when publisher performs an insert,
    apply worker will blindly copy that row to sub's table making identity
    column's duplicate entries.
    
    CREATE TABLE color ( color_id INT GENERATED ALWAYS AS
    IDENTITY,color_name VARCHAR NOT NULL);
    
    Pub: insert into color(color_name) values('red');
    
    Sub: perform sequence refresh and check 'r' state is reached, then do insert:
    insert into color(color_name) values('yellow');
    
    Pub: insert into color(color_name) values('blue');
    
    After above, data on Pub: (1, 'red') ;(2, 'blue'),
    
    After above, data on Sub: (1, 'red') ;(2, 'yellow'); (2, 'blue'),
    
    Identity column has duplicate values. Should the apply worker error
    out while inserting such a  row to the table? Or it is not in the
    scope of this project?
    
    thanks
    Shveta
    
    
    
    
  114. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-08-06T04:24:35Z

    On Tue, Aug 6, 2024 at 8:49 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Mon, Aug 5, 2024 at 5:28 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Mon, Aug 5, 2024 at 2:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Fri, 2 Aug 2024 at 14:24, shveta malik <shveta.malik@gmail.com> wrote:
    > > > >
    > > > > On Thu, Aug 1, 2024 at 9:26 AM shveta malik <shveta.malik@gmail.com> wrote:
    > > > > >
    > > > > > On Mon, Jul 29, 2024 at 4:17 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > >
    > > > > > > Thanks for reporting this, these issues are fixed in the attached
    > > > > > > v20240730_2 version patch.
    > > > > > >
    > > > >
    > > > > I was reviewing the design of patch003, and I have a query. Do we need
    > > > > to even start an apply worker and create replication slot when
    > > > > subscription created is for 'sequences only'? IIUC, currently logical
    > > > > replication apply worker is the one launching sequence-sync worker
    > > > > whenever needed. I think it should be the launcher doing this job and
    > > > > thus apply worker may even not be needed for current functionality of
    > > > > sequence sync?
    > > >
    > >
    > > But that would lead to maintaining all sequence-sync of each
    > > subscription by launcher. Say there are 100 sequences per subscription
    > > and some of them from each subscription are failing due to some
    > > reasons then the launcher will be responsible for ensuring all the
    > > sequences are synced. I think it would be better to handle
    > > per-subscription work by the apply worker.
    >
    > I thought we can give that task to sequence-sync worker. Once sequence
    > sync worker is started by launcher, it keeps on syncing until all the
    > sequences are synced (even failed ones) and then exits only after all
    > are synced; instead of apply worker starting it multiple times for
    > failed sequences. Launcher to start sequence sync worker when signaled
    > by 'alter-sub refresh seq'.
    > But after going through details given by Vignesh in [1], I also see
    > the benefits of using apply worker for this task. Since apply worker
    > is already looping and doing that for table-sync, we can reuse the
    > same code for sequence sync and maintenance will be easy. So looks
    > okay if we go with existing apply worker design.
    >
    
    Fair enough. However, I was wondering whether apply_worker should exit
    after syncing all sequences for a sequence-only subscription or should
    it be there for future commands that can refresh the subscription and
    add additional tables or sequences?
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  115. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-08-06T04:54:18Z

    On Tue, Aug 6, 2024 at 9:54 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Aug 6, 2024 at 8:49 AM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > > > > I was reviewing the design of patch003, and I have a query. Do we need
    > > > > > to even start an apply worker and create replication slot when
    > > > > > subscription created is for 'sequences only'? IIUC, currently logical
    > > > > > replication apply worker is the one launching sequence-sync worker
    > > > > > whenever needed. I think it should be the launcher doing this job and
    > > > > > thus apply worker may even not be needed for current functionality of
    > > > > > sequence sync?
    > > > >
    > > >
    > > > But that would lead to maintaining all sequence-sync of each
    > > > subscription by launcher. Say there are 100 sequences per subscription
    > > > and some of them from each subscription are failing due to some
    > > > reasons then the launcher will be responsible for ensuring all the
    > > > sequences are synced. I think it would be better to handle
    > > > per-subscription work by the apply worker.
    > >
    > > I thought we can give that task to sequence-sync worker. Once sequence
    > > sync worker is started by launcher, it keeps on syncing until all the
    > > sequences are synced (even failed ones) and then exits only after all
    > > are synced; instead of apply worker starting it multiple times for
    > > failed sequences. Launcher to start sequence sync worker when signaled
    > > by 'alter-sub refresh seq'.
    > > But after going through details given by Vignesh in [1], I also see
    > > the benefits of using apply worker for this task. Since apply worker
    > > is already looping and doing that for table-sync, we can reuse the
    > > same code for sequence sync and maintenance will be easy. So looks
    > > okay if we go with existing apply worker design.
    > >
    >
    > Fair enough. However, I was wondering whether apply_worker should exit
    > after syncing all sequences for a sequence-only subscription
    
    If apply worker exits, then on next sequence-refresh, we need a way to
    wake-up launcher to start apply worker which then will start
    table-sync worker. Instead, won't it be better if the launcher starts
    table-sync worker directly without the need of apply worker being
    present (which I stated earlier).
    
    >  or should
    > it be there for future commands that can refresh the subscription and
    > add additional tables or sequences?
    
    If we stick with apply worker starting table sync worker when needed
    by continuously checking seq-sync states ('i'/'r'), then IMO, it is
    better that apply-worker stays. But if we want  apply-worker to exit
    and start only when needed, then why not to start sequence-sync worker
    directly for seq-only subscriptions?
    
    thanks
    Shveta
    
    
    
    
  116. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-06T07:14:17Z

    On Tue, 6 Aug 2024 at 10:24, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Tue, Aug 6, 2024 at 9:54 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Tue, Aug 6, 2024 at 8:49 AM shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > > > > > > I was reviewing the design of patch003, and I have a query. Do we need
    > > > > > > to even start an apply worker and create replication slot when
    > > > > > > subscription created is for 'sequences only'? IIUC, currently logical
    > > > > > > replication apply worker is the one launching sequence-sync worker
    > > > > > > whenever needed. I think it should be the launcher doing this job and
    > > > > > > thus apply worker may even not be needed for current functionality of
    > > > > > > sequence sync?
    > > > > >
    > > > >
    > > > > But that would lead to maintaining all sequence-sync of each
    > > > > subscription by launcher. Say there are 100 sequences per subscription
    > > > > and some of them from each subscription are failing due to some
    > > > > reasons then the launcher will be responsible for ensuring all the
    > > > > sequences are synced. I think it would be better to handle
    > > > > per-subscription work by the apply worker.
    > > >
    > > > I thought we can give that task to sequence-sync worker. Once sequence
    > > > sync worker is started by launcher, it keeps on syncing until all the
    > > > sequences are synced (even failed ones) and then exits only after all
    > > > are synced; instead of apply worker starting it multiple times for
    > > > failed sequences. Launcher to start sequence sync worker when signaled
    > > > by 'alter-sub refresh seq'.
    > > > But after going through details given by Vignesh in [1], I also see
    > > > the benefits of using apply worker for this task. Since apply worker
    > > > is already looping and doing that for table-sync, we can reuse the
    > > > same code for sequence sync and maintenance will be easy. So looks
    > > > okay if we go with existing apply worker design.
    > > >
    > >
    > > Fair enough. However, I was wondering whether apply_worker should exit
    > > after syncing all sequences for a sequence-only subscription
    >
    > If apply worker exits, then on next sequence-refresh, we need a way to
    > wake-up launcher to start apply worker which then will start
    > table-sync worker. Instead, won't it be better if the launcher starts
    > table-sync worker directly without the need of apply worker being
    > present (which I stated earlier).
    
    I favour the current design because it ensures the system remains
    extendable for future incremental sequence synchronization. If the
    launcher were responsible for starting the sequence sync worker, it
    would add extra load that could hinder its ability to service other
    subscriptions and complicate the design for supporting incremental
    sync of sequences. Additionally, this approach offers the other
    benefits mentioned in [1].
    
    > >  or should
    > > it be there for future commands that can refresh the subscription and
    > > add additional tables or sequences?
    >
    > If we stick with apply worker starting table sync worker when needed
    > by continuously checking seq-sync states ('i'/'r'), then IMO, it is
    > better that apply-worker stays. But if we want  apply-worker to exit
    > and start only when needed, then why not to start sequence-sync worker
    > directly for seq-only subscriptions?
    
    There is a risk that sequence synchronization might fail if the
    sequence value from the publisher falls outside the defined minvalue
    or maxvalue range. The apply worker must be active to determine
    whether to initiate the sequence sync worker after the
    wal_retrieve_retry_interval period. Typically, publications consisting
    solely of sequences are uncommon. However, if a user wishes to use
    such publications, they can disable the subscription if necessary and
    re-enable it when a sequence refresh is needed.
    
    [1] - https://www.postgresql.org/message-id/CALDaNm1KO8f3Fj%2BRHHXM%3DUSGwOcW242M1jHee%3DX_chn2ToiCpw%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  117. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-06T09:08:00Z

    Here are some review comments for the patch v20240805_2-0003.
    
    ======
    doc/src/sgml/catalogs.sgml
    
    nitpick - removed the word "either"
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    I felt the discussions about "how to handle warnings" are a bit scattered:
    e.g.1 - ALTER SUBSCRIPTION REFRESH PUBLICATION copy data referred to
    CREATE SUBSCRIPTION copy data.
    e.g.2 - ALTER SUBSCRIPTION REFRESH explains what to do, but now the
    explanation is in 2 places.
    e.g.3 - CREATE SUBSCRIPTION copy data explains what to do (again), but
    IMO it belongs better in the common "Notes" part
    
    FYI, I've moved all the information to one place (in the CREATE
    SUBSCRIPTION "Notes") and others refer to this central place. See the
    attached nitpicks diff.
    
    REFRESH PUBLICATION copy_data
    nitpick - now refers to  CREATE SUBSCRIPTION "Notes". I also moved it
    to be nearer to the other sequence stuff.
    
    REFRESH PUBLICATION SEQUENCES:
    nitpick - now refers to CREATE SUBSCRIPTION "Notes".
    
    ======
    doc/src/sgml/ref/create_subscription.sgml
    
    REFRESH PUBLICATION copy_data
    nitpick - now refers to CREATE SUBSCRIPTION "Notes"
    
    Notes:
    nitpick - the explanation of, and what to do about sequence WARNINGS,
    is moved to here
    
    ======
    src/backend/commands/sequence.c
    
    pg_sequence_state:
    nitpick - I just moved the comment in pg_sequence_state() to below the
    NOTE, which talks about "page LSN".
    
    ======
    src/backend/catalog/pg_subscription.c
    
    1. HasSubscriptionRelations
    
    Should function 'HasSubscriptionRelations' be renamed to
    'HasSubscriptionTables'?
    
    ~~~
    
    GetSubscriptionRelations:
    nitpick - tweak some "skip" comments.
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    2. CreateSubscription
    
      tables = fetch_table_list(wrconn, publications);
    - foreach(lc, tables)
    + foreach_ptr(RangeVar, rv, tables)
    + {
    + Oid relid;
    +
    + relid = RangeVarGetRelid(rv, AccessShareLock, false);
    +
    + /* Check for supported relkind. */
    + CheckSubscriptionRelkind(get_rel_relkind(relid),
    + rv->schemaname, rv->relname);
    +
    + AddSubscriptionRelState(subid, relid, table_state,
    + InvalidXLogRecPtr, true);
    + }
    +
    + /* Add the sequences in init state */
    + sequences = fetch_sequence_list(wrconn, publications);
    + foreach_ptr(RangeVar, rv, sequences)
    
    These 2 loops (first for tables and then for sequences) seem to be
    executing the same code. If you wanted you could combine the lists
    up-front, and then have one code loop instead of 2. It would mean less
    code. OTOH, maybe the current code is more readable? I am not sure
    what is best, so just bringing this to your attention.
    
    ~~~
    
    AlterSubscription_refresh:
    nitpick = typo /indicating tha/indicating that/
    
    ~~~
    
    3. fetch_sequence_list
    
    + appendStringInfoString(&cmd, "SELECT DISTINCT n.nspname, c.relname,
    s.seqtypid, s.seqmin, s.seqmax, s.seqstart, s.seqincrement,
    s.seqcycle"
    +    " FROM pg_publication p, LATERAL
    pg_get_publication_sequences(p.pubname::text) gps(relid),"
    +    " pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace JOIN
    pg_sequence s ON c.oid = s.seqrelid"
    +    " WHERE c.oid = gps.relid AND p.pubname IN (");
    + get_publications_str(publications, &cmd, true);
    + appendStringInfoChar(&cmd, ')');
    
    Please wrap this better to make the SQL more readable.
    
    ~~
    
    4.
    + if (seqform->seqtypid != seqtypid || seqform->seqmin != seqmin ||
    + seqform->seqmax != seqmax || seqform->seqstart != seqstart ||
    + seqform->seqincrement != seqincrement ||
    + seqform->seqcycle != seqcycle)
    + ereport(WARNING,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("Sequence option in remote and local is not same for \"%s.%s\"",
    +    get_namespace_name(get_rel_namespace(relid)), get_rel_name(relid)),
    + errhint("Alter/Re-create the sequence using the same options as in remote."));
    
    4a.
    Are these really known as "options"? Or should they be called
    "sequence parameters", or something else, like "sequence attributes"?
    
    4a.
    Is there a way to give more helpful information by identifying what
    was different in the log? OTOH, maybe it would become too messy if
    there were multiple differences...
    
    ======
    src/backend/replication/logical/launcher.c
    
    5. logicalrep_sync_worker_count
    
    - if (isTablesyncWorker(w) && w->subid == subid)
    + if ((isTableSyncWorker(w) || isSequenceSyncWorker(w)) &&
    + w->subid == subid)
    
    You could micro-optimize this -- it may be more efficient to write the
    condition the other way around.
    
    SUGGESTION
    if (w->subid == subid && (isTableSyncWorker(w) || isSequenceSyncWorker(w)))
    
    ======
    .../replication/logical/sequencesync.c
    
    File header comment:
    nitpick - there seems a large cut/paste mistake (the first 2
    paragraphs are almost the same).
    nitpick - reworded with the help of Chat-GPT for slightly better
    clarity. Also fixed a couple of typos.
    nitpick - it mentioned MAX_SEQUENCES_SYNC_PER_BATCH several times so I
    changed the wording of one of them
    
    ~~~
    
    fetch_remote_sequence_data:
    nitpick - all other params have the same name as sequence members, so
    change the parameter name /lsn/page_lsn/
    
    ~
    
    copy_sequence:
    nitpick - rename var /seq_lsn/seq_page_lsn/
    
    ======
    src/backend/replication/logical/tablesync.c
    
    6. process_syncing_sequences_for_apply
    
    + * If a sequencesync worker is running already, there is no need to start a new
    + * one; the existing sequencesync worker will synchronize all the sequences. If
    + * there are still any sequences to be synced after the sequencesync worker
    + * exited, then a new sequencesync worker can be started in the next iteration.
    + * To prevent starting the sequencesync worker at a high frequency after a
    + * failure, we store its last failure time. We start the sync worker for the
    + * same relation after waiting at least wal_retrieve_retry_interval.
    
    Why is it talking about "We start the sync worker for the same
    relation ...". The sequencesync_failuretime is per sync worker, not
    per relation. And, I don't see any 'same relation' check in the code.
    
    ======
    src/include/catalog/pg_subscription_rel.h
    
    GetSubscriptionRelations:
    nitpick - changed parameter name /all_relations/all_states/
    
    ======
    src/test/subscription/t/034_sequences.pl
    
    nitpick - add some ########## comments to highlight the main test
    parts to make it easier to read.
    nitpick - fix typo /syned/synced/
    
    7. More test cases?
    IIUC you can also get a sequence mismatch warning during "ALTER ...
    REFRESH PUBLICATION", and "CREATE SUBSCRIPTION". So, should those be
    tested also?
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  118. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-06T11:42:27Z

    On Mon, 5 Aug 2024 at 18:05, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Mon, Aug 5, 2024 at 11:04 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Wed, 31 Jul 2024 at 14:39, shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > > > On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    > > > > >
    > > > > >
    > > > > >
    > > > > > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > >>
    > > > > >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > >> [...]
    > > > > >> A new catalog table, pg_subscription_seq, has been introduced for
    > > > > >> mapping subscriptions to sequences. Additionally, the sequence LSN
    > > > > >> (Log Sequence Number) is stored, facilitating determination of
    > > > > >> sequence changes occurring before or after the returned sequence
    > > > > >> state.
    > > > > >
    > > > > >
    > > > > > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    > > > > > something.
    > > > >
    > > > > We'll require the lsn because the sequence LSN informs the user that
    > > > > it has been synchronized up to the LSN in pg_subscription_seq. Since
    > > > > we are not supporting incremental sync, the user will be able to
    > > > > identify if he should run refresh sequences or not by checking the lsn
    > > > > of the pg_subscription_seq and the lsn of the sequence(using
    > > > > pg_sequence_state added) in the publisher.
    > > >
    > > > How the user will know from seq's lsn that he needs to run refresh.
    > > > lsn indicates page_lsn and thus the sequence might advance on pub
    > > > without changing lsn and thus lsn may look the same on subscriber even
    > > > though a sequence-refresh is needed. Am I missing something here?
    > >
    > > When a sequence is synchronized to the subscriber, the page LSN of the
    > > sequence from the publisher is also retrieved and stored in
    > > pg_subscriber_rel as shown below:
    > > --- Publisher page lsn
    > > publisher=# select pg_sequence_state('seq1');
    > >  pg_sequence_state
    > > --------------------
    > >  (0/1510E38,65,1,t)
    > > (1 row)
    > >
    > > --- Subscriber stores the publisher's page lsn for the sequence
    > > subscriber=# select * from pg_subscription_rel where srrelid = 16384;
    > >  srsubid | srrelid | srsubstate | srsublsn
    > > ---------+---------+------------+-----------
    > >    16389 |   16384 | r          | 0/1510E38
    > > (1 row)
    > >
    > > If changes are made to the sequence, such as performing many nextvals,
    > > the page LSN will be updated. Currently the sequence values are
    > > prefetched for SEQ_LOG_VALS 32, so the lsn will not get updated for
    > > the prefetched values, once the prefetched values are consumed the lsn
    > > will get updated.
    > > For example:
    > > --- Updated LSN on the publisher (old lsn - 0/1510E38, new lsn - 0/1558CA8)
    > > publisher=# select pg_sequence_state('seq1');
    > >   pg_sequence_state
    > > ----------------------
    > >  (0/1558CA8,143,22,t)
    > > (1 row)
    > >
    > > The user can then compare this updated value with the sequence's LSN
    > > in pg_subscription_rel to determine when to re-synchronize the
    > > sequence.
    >
    > Thanks for the details. But I was referring to the case where we are
    > in between pre-fetched values on publisher (say at 25th value), while
    > on subscriber we are slightly behind (say at 15th value), but page-lsn
    > will be the same on both. Since the subscriber is behind, a
    > sequence-refresh is needed on sub, but by looking at lsn (which is
    > same), one can not say that for sure.  Let me know if I have
    > misunderstood it.
    
    Yes, at present, if the value is within the pre-fetched range, we
    cannot distinguish it solely using the page_lsn. However, the
    pg_sequence_state function also provides last_value and log_cnt, which
    can be used to handle these specific cases.
    
    Regards,
    Vignesh
    
    
    
    
  119. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-08-07T02:39:09Z

    On Tue, Aug 6, 2024 at 5:13 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 5 Aug 2024 at 18:05, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Mon, Aug 5, 2024 at 11:04 AM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Wed, 31 Jul 2024 at 14:39, shveta malik <shveta.malik@gmail.com> wrote:
    > > > >
    > > > > On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > >
    > > > > > On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    > > > > > >
    > > > > > >
    > > > > > >
    > > > > > > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > >>
    > > > > > >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > >> [...]
    > > > > > >> A new catalog table, pg_subscription_seq, has been introduced for
    > > > > > >> mapping subscriptions to sequences. Additionally, the sequence LSN
    > > > > > >> (Log Sequence Number) is stored, facilitating determination of
    > > > > > >> sequence changes occurring before or after the returned sequence
    > > > > > >> state.
    > > > > > >
    > > > > > >
    > > > > > > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    > > > > > > something.
    > > > > >
    > > > > > We'll require the lsn because the sequence LSN informs the user that
    > > > > > it has been synchronized up to the LSN in pg_subscription_seq. Since
    > > > > > we are not supporting incremental sync, the user will be able to
    > > > > > identify if he should run refresh sequences or not by checking the lsn
    > > > > > of the pg_subscription_seq and the lsn of the sequence(using
    > > > > > pg_sequence_state added) in the publisher.
    > > > >
    > > > > How the user will know from seq's lsn that he needs to run refresh.
    > > > > lsn indicates page_lsn and thus the sequence might advance on pub
    > > > > without changing lsn and thus lsn may look the same on subscriber even
    > > > > though a sequence-refresh is needed. Am I missing something here?
    > > >
    > > > When a sequence is synchronized to the subscriber, the page LSN of the
    > > > sequence from the publisher is also retrieved and stored in
    > > > pg_subscriber_rel as shown below:
    > > > --- Publisher page lsn
    > > > publisher=# select pg_sequence_state('seq1');
    > > >  pg_sequence_state
    > > > --------------------
    > > >  (0/1510E38,65,1,t)
    > > > (1 row)
    > > >
    > > > --- Subscriber stores the publisher's page lsn for the sequence
    > > > subscriber=# select * from pg_subscription_rel where srrelid = 16384;
    > > >  srsubid | srrelid | srsubstate | srsublsn
    > > > ---------+---------+------------+-----------
    > > >    16389 |   16384 | r          | 0/1510E38
    > > > (1 row)
    > > >
    > > > If changes are made to the sequence, such as performing many nextvals,
    > > > the page LSN will be updated. Currently the sequence values are
    > > > prefetched for SEQ_LOG_VALS 32, so the lsn will not get updated for
    > > > the prefetched values, once the prefetched values are consumed the lsn
    > > > will get updated.
    > > > For example:
    > > > --- Updated LSN on the publisher (old lsn - 0/1510E38, new lsn - 0/1558CA8)
    > > > publisher=# select pg_sequence_state('seq1');
    > > >   pg_sequence_state
    > > > ----------------------
    > > >  (0/1558CA8,143,22,t)
    > > > (1 row)
    > > >
    > > > The user can then compare this updated value with the sequence's LSN
    > > > in pg_subscription_rel to determine when to re-synchronize the
    > > > sequence.
    > >
    > > Thanks for the details. But I was referring to the case where we are
    > > in between pre-fetched values on publisher (say at 25th value), while
    > > on subscriber we are slightly behind (say at 15th value), but page-lsn
    > > will be the same on both. Since the subscriber is behind, a
    > > sequence-refresh is needed on sub, but by looking at lsn (which is
    > > same), one can not say that for sure.  Let me know if I have
    > > misunderstood it.
    >
    > Yes, at present, if the value is within the pre-fetched range, we
    > cannot distinguish it solely using the page_lsn.
    >
    
    This makes sense to me.
    
    >
    > However, the
    > pg_sequence_state function also provides last_value and log_cnt, which
    > can be used to handle these specific cases.
    >
    
    BTW, can we document all these steps for users to know when to refresh
    the sequences, if not already documented?
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  120. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-07T04:42:00Z

    Hi Vignesh,
    
    This is mostly a repeat of my previous mail from a while ago [1] but
    includes some corrections, answers, and more examples. I'm going to
    try to persuade one last time because the current patch is becoming
    stable, so I wanted to revisit this syntax proposal before it gets too
    late to change anything.
    
    If there is some problem with the proposed idea please let me know
    because I can see only the advantages and no disadvantages of doing it
    this way.
    
    ~~~
    
    The current patchset offers two forms of subscription refresh:
    1. ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( refresh_option
    [= value] [, ... ] ) ]
    2. ALTER SUBSCRIPTION name REFRESH PUBLICATION SEQUENCES
    
    Since 'copy_data' is the only supported refresh_option, really it is more like:
    1. ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( copy_data [=
    true|false] ) ]
    2. ALTER SUBSCRIPTION name REFRESH PUBLICATION SEQUENCES
    
    ~~~
    
    I proposed previously that instead of having 2 commands for refreshing
    subscriptions we should have a single refresh command:
    
    ALTER SUBSCRIPTION name REFRESH PUBLICATION [TABLES|SEQUENCES] [ WITH
    ( copy_data [= true|false] ) ]
    
    Why?
    
    - IMO it is less confusing than having 2 commands that both refresh
    sequences in slightly different ways
    
    - It is more flexible because apart from refreshing everything, a user
    can choose to refresh only tables or only sequences if desired; IMO
    more flexibility is always good.
    
    - There is no loss of functionality from the current implementation
    AFAICT. You can still say "ALTER SUBSCRIPTION sub REFRESH PUBLICATION
    SEQUENCES" exactly the same as the patchset allows.
    
    - The implementation code will become simpler. For example, the
    current implementation of AlterSubscription_refresh(...) includes the
    (hacky?) 'resync_all_sequences' parameter and has an overcomplicated
    relationship with other parameters as demonstrated by the assertions
    below. IMO using the prosed syntax means this coding will become not
    only simpler, but shorter too.
    + /* resync_all_sequences cannot be specified with refresh_tables */
    + Assert(!(resync_all_sequences && refresh_tables));
    +
    + /* resync_all_sequences cannot be specified with copy_data as false */
    + Assert(!(resync_all_sequences && !copy_data));
    
    ~~~
    
    So, to continue this proposal, let the meaning of 'copy_data' for
    SEQUENCES be as follows:
    
    - when copy_data == false: it means don't copy data (i.e. don't
    synchronize anything). Add/remove sequences from pg_subscriber_rel as
    needed.
    
    - when copy_data == true: it means to copy data (i.e. synchronize) for
    all sequences. Add/remove sequences from pg_subscriber_rel as needed)
    
    
    ~~~
    
    EXAMPLES using the proposed syntax:
    
    Refreshing TABLES only...
    
    ex1.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION TABLES WITH (copy_data = false)
    - same as PG17 functionality for "ALTER SUBSCRIPTION sub REFRESH
    PUBLICATION WITH (copy_data = false)"
    
    ex2.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION TABLES WITH (copy_data = true)
    - same as PG17 functionality for "ALTER SUBSCRIPTION sub REFRESH
    PUBLICATION WITH (copy_data = true)"
    
    ex3. (using default copy_data)
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION TABLES
    - same as ex2.
    
    ~
    
    Refreshing SEQUENCES only...
    
    ex4.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION SEQUENCES WITH (copy data = false)
    - this adds/removes only sequences to pg_subscription_rel but doesn't
    update the sequence values
    
    ex5.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION SEQUENCES WITH (copy data = true)
    - this adds/removes only sequences to pg_subscription_rel and also
    updates (synchronizes) all sequence values.
    - same functionality as "ALTER SUBSCRIPTION sub REFRESH PUBLICATION
    SEQUENCES" in your current patchset
    
    ex6. (using default copy_data)
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION SEQUENCES
    - same as ex5.
    - note, that this command has the same syntax and functionality as the
    current patchset
    
    ~~~
    
    When no object_type is specified it has intuitive meaning to refresh
    both TABLES and SEQUENCES...
    
    ex7.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION WITH (copy_data = false)
    - For tables, it is the same as the PG17 functionality
    - For sequences it includes the same behaviour of ex4.
    
    ex8.
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION WITH (copy_data = true)
    - For tables, it is the same as the PG17 functionality
    - For sequences it includes the same behaviour of ex5.
    - There is one subtle difference from the current patchset because
    this proposal will synchronize *all* sequences instead of only new
    ones. But, this is a good thing. The current documentation is
    complicated by having to explain the differences between REFRESH
    PUBLICATION and REFRESH PUBLICATION SEQUENCES. The current patchset
    also raises questions like how the user chooses whether to use
    "REFRESH PUBLICATION SEQUENCES" versus "REFRESH PUBLICATION WITH
    (copy_data=true)". OTHO, the proposed syntax eliminates ambiguity.
    
    ex9. (using default copy_data)
    ALTER SUBSCRIPTION sub REFRESH PUBLICATION
    - same as ex8
    
    ======
    [1] https://www.postgresql.org/message-id/CAHut%2BPuFH1OCj-P1UKoRQE2X4-0zMG%2BN1V7jdn%3DtOQV4RNbAbw%40mail.gmail.com
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  121. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-08-07T04:57:09Z

    On Mon, Aug 5, 2024 at 10:26 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 1 Aug 2024 at 04:25, Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > Hi Vignesh,
    > >
    > > I noticed that when replicating sequences (using the latest patches
    > > 0730_2*)  the subscriber-side checks the *existence* of the sequence,
    > > but apparently it is not checking other sequence attributes.
    > >
    > > For example, consider:
    > >
    > > Publisher: "CREATE SEQUENCE s1 START 1 INCREMENT 2;" should be a
    > > sequence of only odd numbers.
    > > Subscriber: "CREATE SEQUENCE s1 START 2 INCREMENT 2;" should be a
    > > sequence of only even numbers.
    > >
    > > Because the names match, currently the patch allows replication of the
    > > s1 sequence. I think that might lead to unexpected results on the
    > > subscriber. IMO it might be safer to report ERROR unless the sequences
    > > match properly (i.e. not just a name check).
    > >
    > > Below is a demonstration the problem:
    > >
    > > ==========
    > > Publisher:
    > > ==========
    > >
    > > (publisher sequence is odd numbers)
    > >
    > > test_pub=# create sequence s1 start 1 increment 2;
    > > CREATE SEQUENCE
    > > test_pub=# select * from nextval('s1');
    > >  nextval
    > > ---------
    > >        1
    > > (1 row)
    > >
    > > test_pub=# select * from nextval('s1');
    > >  nextval
    > > ---------
    > >        3
    > > (1 row)
    > >
    > > test_pub=# select * from nextval('s1');
    > >  nextval
    > > ---------
    > >        5
    > > (1 row)
    > >
    > > test_pub=# CREATE PUBLICATION pub1 FOR ALL SEQUENCES;
    > > CREATE PUBLICATION
    > > test_pub=#
    > >
    > > ==========
    > > Subscriber:
    > > ==========
    > >
    > > (subscriber sequence is even numbers)
    > >
    > > test_sub=# create sequence s1 start 2 increment 2;
    > > CREATE SEQUENCE
    > > test_sub=# SELECT * FROM nextval('s1');
    > >  nextval
    > > ---------
    > >        2
    > > (1 row)
    > >
    > > test_sub=# SELECT * FROM nextval('s1');
    > >  nextval
    > > ---------
    > >        4
    > > (1 row)
    > >
    > > test_sub=# SELECT * FROM nextval('s1');
    > >  nextval
    > > ---------
    > >        6
    > > (1 row)
    > >
    > > test_sub=# CREATE SUBSCRIPTION sub1 CONNECTION 'dbname=test_pub'
    > > PUBLICATION pub1;
    > > 2024-08-01 08:43:04.198 AEST [24325] WARNING:  subscriptions created
    > > by regression test cases should have names starting with "regress_"
    > > WARNING:  subscriptions created by regression test cases should have
    > > names starting with "regress_"
    > > NOTICE:  created replication slot "sub1" on publisher
    > > CREATE SUBSCRIPTION
    > > test_sub=# 2024-08-01 08:43:04.294 AEST [26240] LOG:  logical
    > > replication apply worker for subscription "sub1" has started
    > > 2024-08-01 08:43:04.309 AEST [26244] LOG:  logical replication
    > > sequence synchronization worker for subscription "sub1" has started
    > > 2024-08-01 08:43:04.323 AEST [26244] LOG:  logical replication
    > > synchronization for subscription "sub1", sequence "s1" has finished
    > > 2024-08-01 08:43:04.323 AEST [26244] LOG:  logical replication
    > > sequence synchronization worker for subscription "sub1" has finished
    > >
    > > (after the CREATE SUBSCRIPTION we are getting replicated odd values
    > > from the publisher, even though the subscriber side sequence was
    > > supposed to be even numbers)
    > >
    > > test_sub=# SELECT * FROM nextval('s1');
    > >  nextval
    > > ---------
    > >        7
    > > (1 row)
    > >
    > > test_sub=# SELECT * FROM nextval('s1');
    > >  nextval
    > > ---------
    > >        9
    > > (1 row)
    > >
    > > test_sub=# SELECT * FROM nextval('s1');
    > >  nextval
    > > ---------
    > >       11
    > > (1 row)
    > >
    > > (Looking at the description you would expect odd values for this
    > > sequence to be impossible)
    
    I see that for such even sequences, user can still do 'setval'  to a
    odd number and then nextval will keep on returning odd value.
    
    postgres=# SELECT nextval('s1');
           6
    
    postgres=SELECT setval('s1', 43);
         43
    
    postgres=# SELECT nextval('s1');
         45
    
    > > test_sub=# \dS+ s1
    > >                              Sequence "public.s1"
    > >   Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache
    > > --------+-------+---------+---------------------+-----------+---------+-------
    > >  bigint |     2 |       1 | 9223372036854775807 |         2 | no      |     1
    >
    > Even if we check the sequence definition during the CREATE
    > SUBSCRIPTION/ALTER SUBSCRIPTION ... REFRESH PUBLICATION or ALTER
    > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES commands, there's still
    > a chance that the sequence definition might change after the command
    > has been executed. Currently, there's no mechanism to lock a sequence,
    > and we also permit replication of table data even if the table
    > structures differ, such as mismatched data types like int and
    > smallint. I have modified it to log a warning to inform users that the
    > sequence options on the publisher and subscriber are not the same and
    > advise them to ensure that the sequence definitions are consistent
    > between both.
    > The v20240805 version patch attached at [1] has the changes for the same.
    > [1] - https://www.postgresql.org/message-id/CALDaNm1Y_ot-jFRfmtwDuwmFrgSSYHjVuy28RspSopTtwzXy8w%40mail.gmail.com
    
    The behavior for applying is no different from setval. Having said
    that, I agree that sequence definition can change even after the
    subscription creation, but earlier we were not syncing sequences and
    thus the value of a particular sequence was going to remain in the
    range/pattern defined by its attributes unless user sets it manually
    using setval. But now, it is being changed in the background without
    user's knowledge.
    The table case is different. In case of table replication, if we have
    CHECK constraint or say primary-key etc, then the value which violates
    these constraints will never be  inserted to a table even during
    replication on sub. For sequences, parameters (MIN,MAX, START,
    INCREMENT) can be considered similar to check-constraints, the only
    difference is during apply, we are still overriding these and copying
    pub's value. May be such inconsistencies detection can be targeted
    later in next project. But for the time being, it will be good to add
    a 'caveat' section in doc mentioning all such cases. The scope of this
    project should be clearly documented.
    
    thanks
    Shveta
    
    
    
    
  122. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-07T08:15:39Z

    On Tue, 6 Aug 2024 at 14:38, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Here are some review comments for the patch v20240805_2-0003.
    >
    > 4a.
    > Is there a way to give more helpful information by identifying what
    > was different in the log? OTOH, maybe it would become too messy if
    > there were multiple differences...
    
    I had considered this while implementing and did not implement it to
    print each of the parameters because it will be too messy. I felt
    existing is better.
    
    >
    > 7. More test cases?
    > IIUC you can also get a sequence mismatch warning during "ALTER ...
    > REFRESH PUBLICATION", and "CREATE SUBSCRIPTION". So, should those be
    > tested also?
    
    Since it won't add any extra coverage, I feel no need to add this test.
    
    The remaining comments have been addressed, and the changes are
    included in the attached v20240807 version patch.
    
    Regards,
    Vignesh
    
  123. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-07T08:25:36Z

    On Tue, 6 Aug 2024 at 09:28, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Tue, Aug 6, 2024 at 8:49 AM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    >
    > Do we need some kind of coordination between table sync and sequence
    > sync for internally generated sequences? Lets say we have an identity
    > column with a 'GENERATED ALWAYS' sequence. When the sequence is synced
    > to subscriber, subscriber can also do an insert to table (extra one)
    > incrementing the sequence and then when publisher performs an insert,
    > apply worker will blindly copy that row to sub's table making identity
    > column's duplicate entries.
    >
    > CREATE TABLE color ( color_id INT GENERATED ALWAYS AS
    > IDENTITY,color_name VARCHAR NOT NULL);
    >
    > Pub: insert into color(color_name) values('red');
    >
    > Sub: perform sequence refresh and check 'r' state is reached, then do insert:
    > insert into color(color_name) values('yellow');
    >
    > Pub: insert into color(color_name) values('blue');
    >
    > After above, data on Pub: (1, 'red') ;(2, 'blue'),
    >
    > After above, data on Sub: (1, 'red') ;(2, 'yellow'); (2, 'blue'),
    >
    > Identity column has duplicate values. Should the apply worker error
    > out while inserting such a  row to the table? Or it is not in the
    > scope of this project?
    
    This behavior is documented at [1]:
    Sequence data is not replicated. The data in serial or identity
    columns backed by sequences will of course be replicated as part of
    the table, but the sequence itself would still show the start value on
    the subscriber.
    
    This behavior is because of the above logical replication restriction.
    So the behavior looks ok to me and I feel this is not part of the
    scope of this project. I have updated this documentation section here
    to mention sequences can be updated using ALTER SEQUENCE ... REFRESH
    PUBLICATION SEQUENCES at v20240807 version patch attached at [2].
    
    [1] - https://www.postgresql.org/docs/devel/logical-replication-restrictions.html
    [2] - https://www.postgresql.org/message-id/CALDaNm01Z6Oo9osGMFTOoyTR1kVoyh1rEvZ%2B6uJn-ZymV%3D0dbQ%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  124. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-07T08:29:03Z

    On Mon, 5 Aug 2024 at 17:28, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Mon, Aug 5, 2024 at 2:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Fri, 2 Aug 2024 at 14:24, shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > > > On Thu, Aug 1, 2024 at 9:26 AM shveta malik <shveta.malik@gmail.com> wrote:
    > > > >
    > > > > On Mon, Jul 29, 2024 at 4:17 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > >
    > > > > > Thanks for reporting this, these issues are fixed in the attached
    > > > > > v20240730_2 version patch.
    > > > > >
    > > >
    > > > I was reviewing the design of patch003, and I have a query. Do we need
    > > > to even start an apply worker and create replication slot when
    > > > subscription created is for 'sequences only'? IIUC, currently logical
    > > > replication apply worker is the one launching sequence-sync worker
    > > > whenever needed. I think it should be the launcher doing this job and
    > > > thus apply worker may even not be needed for current functionality of
    > > > sequence sync?
    > >
    >
    > But that would lead to maintaining all sequence-sync of each
    > subscription by launcher. Say there are 100 sequences per subscription
    > and some of them from each subscription are failing due to some
    > reasons then the launcher will be responsible for ensuring all the
    > sequences are synced. I think it would be better to handle
    > per-subscription work by the apply worker.
    >
    > >
    > > Going forward when we implement incremental sync of
    > > > sequences, then we may have apply worker started but now it is not
    > > > needed.
    > >
    > > I believe the current method of having the apply worker initiate the
    > > sequence sync worker is advantageous for several reasons:
    > > a) Reduces Launcher Load: This approach prevents overloading the
    > > launcher, which must handle various other subscription requests.
    > > b) Facilitates Incremental Sync: It provides a more straightforward
    > > path to extend support for incremental sequence synchronization.
    > > c) Reuses Existing Code: It leverages the existing tablesync worker
    > > code for starting the tablesync process, avoiding the need to
    > > duplicate code in the launcher.
    > > d) Simplified Code Maintenance: Centralizing sequence synchronization
    > > logic within the apply worker can simplify code maintenance and
    > > updates, as changes will only need to be made in one place rather than
    > > across multiple components.
    > > e) Better Monitoring and Debugging: With sequence synchronization
    > > being handled by the apply worker, you can more effectively monitor
    > > and debug synchronization processes since all related operations are
    > > managed by a single component.
    > >
    > > Also, I noticed that even when a publication has no tables, we create
    > > replication slot and start apply worker.
    > >
    >
    > As far as I understand slots and origins are primarily required for
    > incremental sync. Would it be used only for sequence-sync cases? If
    > not then we can avoid creating those. I agree that it would add some
    > complexity to the code with sequence-specific checks, so we can create
    > a top-up patch for this if required and evaluate its complexity versus
    > the benefit it produces.
    
    I have added a XXX todo comments in the v20240807 version patch
    attached at [1]. I will handle this as a separate patch once the
    current patch is stable.
    [1] - https://www.postgresql.org/message-id/CALDaNm01Z6Oo9osGMFTOoyTR1kVoyh1rEvZ%2B6uJn-ZymV%3D0dbQ%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  125. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-07T08:30:34Z

    On Wed, 7 Aug 2024 at 08:09, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Aug 6, 2024 at 5:13 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Mon, 5 Aug 2024 at 18:05, shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > > > On Mon, Aug 5, 2024 at 11:04 AM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > On Wed, 31 Jul 2024 at 14:39, shveta malik <shveta.malik@gmail.com> wrote:
    > > > > >
    > > > > > On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > >
    > > > > > > On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    > > > > > > >
    > > > > > > >
    > > > > > > >
    > > > > > > > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > > >>
    > > > > > > >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > > >> [...]
    > > > > > > >> A new catalog table, pg_subscription_seq, has been introduced for
    > > > > > > >> mapping subscriptions to sequences. Additionally, the sequence LSN
    > > > > > > >> (Log Sequence Number) is stored, facilitating determination of
    > > > > > > >> sequence changes occurring before or after the returned sequence
    > > > > > > >> state.
    > > > > > > >
    > > > > > > >
    > > > > > > > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    > > > > > > > something.
    > > > > > >
    > > > > > > We'll require the lsn because the sequence LSN informs the user that
    > > > > > > it has been synchronized up to the LSN in pg_subscription_seq. Since
    > > > > > > we are not supporting incremental sync, the user will be able to
    > > > > > > identify if he should run refresh sequences or not by checking the lsn
    > > > > > > of the pg_subscription_seq and the lsn of the sequence(using
    > > > > > > pg_sequence_state added) in the publisher.
    > > > > >
    > > > > > How the user will know from seq's lsn that he needs to run refresh.
    > > > > > lsn indicates page_lsn and thus the sequence might advance on pub
    > > > > > without changing lsn and thus lsn may look the same on subscriber even
    > > > > > though a sequence-refresh is needed. Am I missing something here?
    > > > >
    > > > > When a sequence is synchronized to the subscriber, the page LSN of the
    > > > > sequence from the publisher is also retrieved and stored in
    > > > > pg_subscriber_rel as shown below:
    > > > > --- Publisher page lsn
    > > > > publisher=# select pg_sequence_state('seq1');
    > > > >  pg_sequence_state
    > > > > --------------------
    > > > >  (0/1510E38,65,1,t)
    > > > > (1 row)
    > > > >
    > > > > --- Subscriber stores the publisher's page lsn for the sequence
    > > > > subscriber=# select * from pg_subscription_rel where srrelid = 16384;
    > > > >  srsubid | srrelid | srsubstate | srsublsn
    > > > > ---------+---------+------------+-----------
    > > > >    16389 |   16384 | r          | 0/1510E38
    > > > > (1 row)
    > > > >
    > > > > If changes are made to the sequence, such as performing many nextvals,
    > > > > the page LSN will be updated. Currently the sequence values are
    > > > > prefetched for SEQ_LOG_VALS 32, so the lsn will not get updated for
    > > > > the prefetched values, once the prefetched values are consumed the lsn
    > > > > will get updated.
    > > > > For example:
    > > > > --- Updated LSN on the publisher (old lsn - 0/1510E38, new lsn - 0/1558CA8)
    > > > > publisher=# select pg_sequence_state('seq1');
    > > > >   pg_sequence_state
    > > > > ----------------------
    > > > >  (0/1558CA8,143,22,t)
    > > > > (1 row)
    > > > >
    > > > > The user can then compare this updated value with the sequence's LSN
    > > > > in pg_subscription_rel to determine when to re-synchronize the
    > > > > sequence.
    > > >
    > > > Thanks for the details. But I was referring to the case where we are
    > > > in between pre-fetched values on publisher (say at 25th value), while
    > > > on subscriber we are slightly behind (say at 15th value), but page-lsn
    > > > will be the same on both. Since the subscriber is behind, a
    > > > sequence-refresh is needed on sub, but by looking at lsn (which is
    > > > same), one can not say that for sure.  Let me know if I have
    > > > misunderstood it.
    > >
    > > Yes, at present, if the value is within the pre-fetched range, we
    > > cannot distinguish it solely using the page_lsn.
    > >
    >
    > This makes sense to me.
    >
    > >
    > > However, the
    > > pg_sequence_state function also provides last_value and log_cnt, which
    > > can be used to handle these specific cases.
    > >
    >
    > BTW, can we document all these steps for users to know when to refresh
    > the sequences, if not already documented?
    
    This has been documented in the v20240807 version attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm01Z6Oo9osGMFTOoyTR1kVoyh1rEvZ%2B6uJn-ZymV%3D0dbQ%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  126. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-08T03:00:28Z

    Hi Vignesh, Here are my v20240807-0003 review comments.
    
    ======
    1. GENERAL DOCS.
    
    IMO the replication of SEQUENCES is a big enough topic that it
    deserves to have its own section in the docs chapter 31 [1].
    
    Some of the create/alter subscription docs content would stay where it
    is in, but a new chapter would just tie everything together better. It
    could also serve as a better place to describe the other sequence
    replication content like:
    (a) getting a WARNING for mismatched sequences and how to handle it.
    (b) how can the user know when a subscription refresh is required to
    (re-)synchronise sequences
    (c) pub/sub examples
    
    ======
    doc/src/sgml/logical-replication.sgml
    
    2. Restrictions
    
    Sequence data is not replicated. The data in serial or identity
    columns backed by sequences will of course be replicated as part of
    the table, but the sequence itself would still show the start value on
    the subscriber. If the subscriber is used as a read-only database,
    then this should typically not be a problem. If, however, some kind of
    switchover or failover to the subscriber database is intended, then
    the sequences would need to be updated to the latest values, either by
    executing ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES or by
    copying the current data from the publisher (perhaps using pg_dump) or
    by determining a sufficiently high value from the tables themselves.
    
    ~
    
    2a.
    The paragraph starts by saying "Sequence data is not replicated.". It
    seems wrong now. Doesn't that need rewording or removing?
    
    ~
    
    2b.
    Should the info "If, however, some kind of switchover or failover..."
    be mentioned in the "Logical Replication Failover" section [2],
    instead of here?
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    3.
    Sequence values may occasionally become out of sync due to updates in
    the publisher. To verify this, compare the
    pg_subscription_rel.srsublsn on the subscriber with the page_lsn
    obtained from the pg_sequence_state for the sequence on the publisher.
    If the sequence is still using prefetched values, the page_lsn will
    not be updated. In such cases, you will need to directly compare the
    sequences and execute REFRESH PUBLICATION SEQUENCES if required.
    
    ~
    
    3a.
    This whole paragraph may be better put in the new chapter that was
    suggested earlier in review comment #1.
    
    ~
    
    3b.
    Is it only "Occasionally"? I expected subscriber-side sequences could
    become stale quite often.
    
    ~
    
    3c.
    Is this advice very useful? It's saying if the LSN is different then
    the sequence is out of date, but if the LSN is not different then you
    cannot tell. Why not ignore LSN altogether and just advise the user to
    directly compare the sequences in the first place?
    
    ======
    
    Also, there are more minor suggestions in the attached nitpicks diff.
    
    ======
    [1] https://www.postgresql.org/docs/current/logical-replication.html
    [2] file:///usr/local/pg_oss/share/doc/postgresql/html/logical-replication-failover.html
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  127. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-08-08T03:55:04Z

    On Wed, Aug 7, 2024 at 10:12 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > This is mostly a repeat of my previous mail from a while ago [1] but
    > includes some corrections, answers, and more examples. I'm going to
    > try to persuade one last time because the current patch is becoming
    > stable, so I wanted to revisit this syntax proposal before it gets too
    > late to change anything.
    >
    > If there is some problem with the proposed idea please let me know
    > because I can see only the advantages and no disadvantages of doing it
    > this way.
    >
    > ~~~
    >
    > The current patchset offers two forms of subscription refresh:
    > 1. ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( refresh_option
    > [= value] [, ... ] ) ]
    > 2. ALTER SUBSCRIPTION name REFRESH PUBLICATION SEQUENCES
    >
    > Since 'copy_data' is the only supported refresh_option, really it is more like:
    > 1. ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( copy_data [=
    > true|false] ) ]
    > 2. ALTER SUBSCRIPTION name REFRESH PUBLICATION SEQUENCES
    >
    > ~~~
    >
    > I proposed previously that instead of having 2 commands for refreshing
    > subscriptions we should have a single refresh command:
    >
    > ALTER SUBSCRIPTION name REFRESH PUBLICATION [TABLES|SEQUENCES] [ WITH
    > ( copy_data [= true|false] ) ]
    >
    > Why?
    >
    > - IMO it is less confusing than having 2 commands that both refresh
    > sequences in slightly different ways
    >
    > - It is more flexible because apart from refreshing everything, a user
    > can choose to refresh only tables or only sequences if desired; IMO
    > more flexibility is always good.
    >
    > - There is no loss of functionality from the current implementation
    > AFAICT. You can still say "ALTER SUBSCRIPTION sub REFRESH PUBLICATION
    > SEQUENCES" exactly the same as the patchset allows.
    >
    > ~~~
    >
    > So, to continue this proposal, let the meaning of 'copy_data' for
    > SEQUENCES be as follows:
    >
    > - when copy_data == false: it means don't copy data (i.e. don't
    > synchronize anything). Add/remove sequences from pg_subscriber_rel as
    > needed.
    >
    > - when copy_data == true: it means to copy data (i.e. synchronize) for
    > all sequences. Add/remove sequences from pg_subscriber_rel as needed)
    >
    
    I find overloading the copy_data option more confusing than adding a
    new variant for REFRESH. To make it clear, we can even think of
    extending the command as ALTER SUBSCRIPTION name REFRESH PUBLICATION
    ALL SEQUENCES or something like that.  I don't know where there is a
    need or not but one can imagine extending it as ALTER SUBSCRIPTION
    name REFRESH PUBLICATION SEQUENCES [<seq_name_1>, <seq_name_2>, ..].
    This will allow to selectively refresh the sequences.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  128. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-08T05:38:48Z

    On Thu, Aug 8, 2024 at 1:55 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Wed, Aug 7, 2024 at 10:12 AM Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > This is mostly a repeat of my previous mail from a while ago [1] but
    > > includes some corrections, answers, and more examples. I'm going to
    > > try to persuade one last time because the current patch is becoming
    > > stable, so I wanted to revisit this syntax proposal before it gets too
    > > late to change anything.
    > >
    > > If there is some problem with the proposed idea please let me know
    > > because I can see only the advantages and no disadvantages of doing it
    > > this way.
    > >
    > > ~~~
    > >
    > > The current patchset offers two forms of subscription refresh:
    > > 1. ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( refresh_option
    > > [= value] [, ... ] ) ]
    > > 2. ALTER SUBSCRIPTION name REFRESH PUBLICATION SEQUENCES
    > >
    > > Since 'copy_data' is the only supported refresh_option, really it is more like:
    > > 1. ALTER SUBSCRIPTION name REFRESH PUBLICATION [ WITH ( copy_data [=
    > > true|false] ) ]
    > > 2. ALTER SUBSCRIPTION name REFRESH PUBLICATION SEQUENCES
    > >
    > > ~~~
    > >
    > > I proposed previously that instead of having 2 commands for refreshing
    > > subscriptions we should have a single refresh command:
    > >
    > > ALTER SUBSCRIPTION name REFRESH PUBLICATION [TABLES|SEQUENCES] [ WITH
    > > ( copy_data [= true|false] ) ]
    > >
    > > Why?
    > >
    > > - IMO it is less confusing than having 2 commands that both refresh
    > > sequences in slightly different ways
    > >
    > > - It is more flexible because apart from refreshing everything, a user
    > > can choose to refresh only tables or only sequences if desired; IMO
    > > more flexibility is always good.
    > >
    > > - There is no loss of functionality from the current implementation
    > > AFAICT. You can still say "ALTER SUBSCRIPTION sub REFRESH PUBLICATION
    > > SEQUENCES" exactly the same as the patchset allows.
    > >
    > > ~~~
    > >
    > > So, to continue this proposal, let the meaning of 'copy_data' for
    > > SEQUENCES be as follows:
    > >
    > > - when copy_data == false: it means don't copy data (i.e. don't
    > > synchronize anything). Add/remove sequences from pg_subscriber_rel as
    > > needed.
    > >
    > > - when copy_data == true: it means to copy data (i.e. synchronize) for
    > > all sequences. Add/remove sequences from pg_subscriber_rel as needed)
    > >
    >
    > I find overloading the copy_data option more confusing than adding a
    > new variant for REFRESH. To make it clear, we can even think of
    > extending the command as ALTER SUBSCRIPTION name REFRESH PUBLICATION
    > ALL SEQUENCES or something like that.  I don't know where there is a
    > need or not but one can imagine extending it as ALTER SUBSCRIPTION
    > name REFRESH PUBLICATION SEQUENCES [<seq_name_1>, <seq_name_2>, ..].
    > This will allow to selectively refresh the sequences.
    >
    
    But, I haven't invented a new overloading for "copy_data" option
    (meaning "synchronize") for sequences. The current patchset already
    interprets copy_data exactly this way.
    
    For example, below are patch 0003 results:
    
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION WITH (copy_data=false)
    - this will add/remove new sequences in pg_subscription_rel, but it
    will *not* synchronize the new sequence
    
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION WITH (copy_data=true)
    - this will add/remove new sequences in pg_subscription_rel, and it
    *will* synchronize the new sequence
    
    ~
    
    I only proposed that copy_data should apply to *all* sequences, not
    just new ones.
    
    ======
    Kind Regards.
    Peter Smith.
    Fujitsu Australia.
    
    
    
    
  129. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-08-08T06:50:59Z

    On Wed, Aug 7, 2024 at 1:45 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > The remaining comments have been addressed, and the changes are
    > included in the attached v20240807 version patch.
    
    Thanks for addressing the comment. Please find few comments for v20240807 :
    
    patch002:
    1)
    create_publication.sgml:
    
    --I think it will be good to add another example for both tables and sequences:
    CREATE PUBLICATION all_sequences FOR ALL TABLES, SEQUENCES;
    I was trying FOR ALL TABLES, FOR ALL SEQUENCES; but I think it is not
    the correct way, so good to have the correct way mentioned in one
    example.
    
    patch003:
    2)
    
     * The page_lsn allows the user to determine if the sequence has been updated
     * since the last synchronization with the subscriber. This is done by
     * comparing the current page_lsn with the value stored in pg_subscription_rel
     * from the last synchronization.
     */
    Datum
    pg_sequence_state(PG_FUNCTION_ARGS)
    
    --This information is still incomplete. Maybe we should mention the
    other attribute name as well which helps to determine this.
    
    3)
    Shall process_syncing_sequences_for_apply() be moved to sequencesync.c
    
    4)
    Would it be better to give a single warning for all unequal sequences
    (comma separated list of sequenec names?)
    
    postgres=# create subscription sub1 connection '....' publication pub1;
    WARNING:  Sequence parameter in remote and local is not same for "public.myseq2"
    HINT:  Alter/Re-create the sequence using the same parameter as in remote.
    WARNING:  Sequence parameter in remote and local is not same for "public.myseq0"
    HINT:  Alter/Re-create the sequence using the same parameter as in remote.
    WARNING:  Sequence parameter in remote and local is not same for "public.myseq4"
    HINT:  Alter/Re-create the sequence using the same parameter as in remote.
    
    
    5)
    IIUC, sequencesync_failure_time is changed by multiple processes.
    Seq-sync worker sets it before exiting on failure, while apply worker
    resets it. Also, the applied worker reads it at a few places. Shall it
    be accessed using LogicalRepWorkerLock?
    
    6)
    process_syncing_sequences_for_apply():
    
    --I feel MyLogicalRepWorker->sequencesync_failure_time should be reset
    to 0 after we are sure that logicalrep_worker_launch() has launched
    the worker without any error. But not sure what could be the clean way
    to do it? If we move it after logicalrep_worker_launch() call, there
    are chances that seq-sync worker has started and failed already and
    has set this failure time which will then be mistakenly reset by apply
    worker. Also moving it inside logicalrep_worker_launch() does not seem
    a good way.
    
    7)
    sequencesync.c
    PostgreSQL logical replication: initial sequence synchronization
    
    --Since it is called by REFRESH also. So shall we remove 'initial'?
    
    8)
    /*
    * Process any tables that are being synchronized in parallel and
    * any newly added relations.
    */
    process_syncing_relations(last_received);
    
    --I did not understand the comment very well. Why are we using 2
    separate words 'tables' and 'relations'? I feel we should have
    mentioned sequences too in the comment.
    
    
    9)
    logical-replication.sgml: Sequence data is not replicated.
    
    --I feel we should rephrase this line now to indicate that it could be
    replicated by the new options.
    
    thanks
    Shveta
    
    
    
    
  130. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2024-08-08T09:27:20Z

    On Thu, Aug 8, 2024 at 11:09 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > But, I haven't invented a new overloading for "copy_data" option
    > (meaning "synchronize") for sequences. The current patchset already
    > interprets copy_data exactly this way.
    >
    > For example, below are patch 0003 results:
    >
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION WITH (copy_data=false)
    > - this will add/remove new sequences in pg_subscription_rel, but it
    > will *not* synchronize the new sequence
    >
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION WITH (copy_data=true)
    > - this will add/remove new sequences in pg_subscription_rel, and it
    > *will* synchronize the new sequence
    >
    > ~
    >
    > I only proposed that copy_data should apply to *all* sequences, not
    > just new ones.
    >
    
    I don't like this difference because for tables, it would *not*
    consider syncing already the existing tables whereas for sequences it
    would consider syncing existing ones. We previously discussed adding a
    new option like copy_all_sequences instead of adding a new variant of
    command but that has its own set of problems, so we agreed to proceed
    with a new variant. See [1] ( ...Good point. And I understood that the
    REFRESH PUBLICATION SEQUENCES command would be helpful when users want
    to synchronize sequences between two nodes before upgrading.).
    
    Having said that, if others also prefer to use copy_data for this
    purpose with a different meaning of this option w.r.t tables and
    sequences then we can still consider it.
    
    [1] - https://www.postgresql.org/message-id/CAD21AoAAszSeHNRha4HND8b9XyzNrx6jbA7t3Mbe%2BfH4hNRj9A%40mail.gmail.com
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  131. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-08T15:52:15Z

    On Thu, 8 Aug 2024 at 08:30, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh, Here are my v20240807-0003 review comments.
    >
    > 2a.
    > The paragraph starts by saying "Sequence data is not replicated.". It
    > seems wrong now. Doesn't that need rewording or removing?
    
    Changed it to incremental sequence changes.
    
    > ~
    >
    > 2b.
    > Should the info "If, however, some kind of switchover or failover..."
    > be mentioned in the "Logical Replication Failover" section [2],
    > instead of here?
    
    I think mentioning this here is appropriate. The other section focuses
    more on how logical replication can proceed with a new primary. Once
    the logical replication setup is complete, sequences can be refreshed
    at any time.
    
    Rest of the comments  are fixed,  the attached v20240808 version patch
    has the changes for the same.
    
    Regards,
    Vignesh
    
  132. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-08T15:55:03Z

    On Wed, 7 Aug 2024 at 10:27, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Mon, Aug 5, 2024 at 10:26 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Thu, 1 Aug 2024 at 04:25, Peter Smith <smithpb2250@gmail.com> wrote:
    > > >
    > > > Hi Vignesh,
    > > >
    > > > I noticed that when replicating sequences (using the latest patches
    > > > 0730_2*)  the subscriber-side checks the *existence* of the sequence,
    > > > but apparently it is not checking other sequence attributes.
    > > >
    > > > For example, consider:
    > > >
    > > > Publisher: "CREATE SEQUENCE s1 START 1 INCREMENT 2;" should be a
    > > > sequence of only odd numbers.
    > > > Subscriber: "CREATE SEQUENCE s1 START 2 INCREMENT 2;" should be a
    > > > sequence of only even numbers.
    > > >
    > > > Because the names match, currently the patch allows replication of the
    > > > s1 sequence. I think that might lead to unexpected results on the
    > > > subscriber. IMO it might be safer to report ERROR unless the sequences
    > > > match properly (i.e. not just a name check).
    > > >
    > > > Below is a demonstration the problem:
    > > >
    > > > ==========
    > > > Publisher:
    > > > ==========
    > > >
    > > > (publisher sequence is odd numbers)
    > > >
    > > > test_pub=# create sequence s1 start 1 increment 2;
    > > > CREATE SEQUENCE
    > > > test_pub=# select * from nextval('s1');
    > > >  nextval
    > > > ---------
    > > >        1
    > > > (1 row)
    > > >
    > > > test_pub=# select * from nextval('s1');
    > > >  nextval
    > > > ---------
    > > >        3
    > > > (1 row)
    > > >
    > > > test_pub=# select * from nextval('s1');
    > > >  nextval
    > > > ---------
    > > >        5
    > > > (1 row)
    > > >
    > > > test_pub=# CREATE PUBLICATION pub1 FOR ALL SEQUENCES;
    > > > CREATE PUBLICATION
    > > > test_pub=#
    > > >
    > > > ==========
    > > > Subscriber:
    > > > ==========
    > > >
    > > > (subscriber sequence is even numbers)
    > > >
    > > > test_sub=# create sequence s1 start 2 increment 2;
    > > > CREATE SEQUENCE
    > > > test_sub=# SELECT * FROM nextval('s1');
    > > >  nextval
    > > > ---------
    > > >        2
    > > > (1 row)
    > > >
    > > > test_sub=# SELECT * FROM nextval('s1');
    > > >  nextval
    > > > ---------
    > > >        4
    > > > (1 row)
    > > >
    > > > test_sub=# SELECT * FROM nextval('s1');
    > > >  nextval
    > > > ---------
    > > >        6
    > > > (1 row)
    > > >
    > > > test_sub=# CREATE SUBSCRIPTION sub1 CONNECTION 'dbname=test_pub'
    > > > PUBLICATION pub1;
    > > > 2024-08-01 08:43:04.198 AEST [24325] WARNING:  subscriptions created
    > > > by regression test cases should have names starting with "regress_"
    > > > WARNING:  subscriptions created by regression test cases should have
    > > > names starting with "regress_"
    > > > NOTICE:  created replication slot "sub1" on publisher
    > > > CREATE SUBSCRIPTION
    > > > test_sub=# 2024-08-01 08:43:04.294 AEST [26240] LOG:  logical
    > > > replication apply worker for subscription "sub1" has started
    > > > 2024-08-01 08:43:04.309 AEST [26244] LOG:  logical replication
    > > > sequence synchronization worker for subscription "sub1" has started
    > > > 2024-08-01 08:43:04.323 AEST [26244] LOG:  logical replication
    > > > synchronization for subscription "sub1", sequence "s1" has finished
    > > > 2024-08-01 08:43:04.323 AEST [26244] LOG:  logical replication
    > > > sequence synchronization worker for subscription "sub1" has finished
    > > >
    > > > (after the CREATE SUBSCRIPTION we are getting replicated odd values
    > > > from the publisher, even though the subscriber side sequence was
    > > > supposed to be even numbers)
    > > >
    > > > test_sub=# SELECT * FROM nextval('s1');
    > > >  nextval
    > > > ---------
    > > >        7
    > > > (1 row)
    > > >
    > > > test_sub=# SELECT * FROM nextval('s1');
    > > >  nextval
    > > > ---------
    > > >        9
    > > > (1 row)
    > > >
    > > > test_sub=# SELECT * FROM nextval('s1');
    > > >  nextval
    > > > ---------
    > > >       11
    > > > (1 row)
    > > >
    > > > (Looking at the description you would expect odd values for this
    > > > sequence to be impossible)
    >
    > I see that for such even sequences, user can still do 'setval'  to a
    > odd number and then nextval will keep on returning odd value.
    >
    > postgres=# SELECT nextval('s1');
    >        6
    >
    > postgres=SELECT setval('s1', 43);
    >      43
    >
    > postgres=# SELECT nextval('s1');
    >      45
    >
    > > > test_sub=# \dS+ s1
    > > >                              Sequence "public.s1"
    > > >   Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache
    > > > --------+-------+---------+---------------------+-----------+---------+-------
    > > >  bigint |     2 |       1 | 9223372036854775807 |         2 | no      |     1
    > >
    > > Even if we check the sequence definition during the CREATE
    > > SUBSCRIPTION/ALTER SUBSCRIPTION ... REFRESH PUBLICATION or ALTER
    > > SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES commands, there's still
    > > a chance that the sequence definition might change after the command
    > > has been executed. Currently, there's no mechanism to lock a sequence,
    > > and we also permit replication of table data even if the table
    > > structures differ, such as mismatched data types like int and
    > > smallint. I have modified it to log a warning to inform users that the
    > > sequence options on the publisher and subscriber are not the same and
    > > advise them to ensure that the sequence definitions are consistent
    > > between both.
    > > The v20240805 version patch attached at [1] has the changes for the same.
    > > [1] - https://www.postgresql.org/message-id/CALDaNm1Y_ot-jFRfmtwDuwmFrgSSYHjVuy28RspSopTtwzXy8w%40mail.gmail.com
    >
    > The behavior for applying is no different from setval. Having said
    > that, I agree that sequence definition can change even after the
    > subscription creation, but earlier we were not syncing sequences and
    > thus the value of a particular sequence was going to remain in the
    > range/pattern defined by its attributes unless user sets it manually
    > using setval. But now, it is being changed in the background without
    > user's knowledge.
    > The table case is different. In case of table replication, if we have
    > CHECK constraint or say primary-key etc, then the value which violates
    > these constraints will never be  inserted to a table even during
    > replication on sub. For sequences, parameters (MIN,MAX, START,
    > INCREMENT) can be considered similar to check-constraints, the only
    > difference is during apply, we are still overriding these and copying
    > pub's value. May be such inconsistencies detection can be targeted
    > later in next project. But for the time being, it will be good to add
    > a 'caveat' section in doc mentioning all such cases. The scope of this
    > project should be clearly documented.
    
    I have added a Caveats section and mentioned it.
    The changes for the same are available at v20240808 version attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm1QQK_Pgx35LrJGuRxBzzYSO8rm1YGJF4w8hYc3Gm%2B5NQ%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  133. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-09T00:20:43Z

    Hi Vignesh, I reviewed the latest v20240808-0003 patch.
    
    Attached are my minor change suggestions.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  134. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-08-09T06:43:00Z

    On Wed, Aug 7, 2024 at 2:00 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 7 Aug 2024 at 08:09, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Tue, Aug 6, 2024 at 5:13 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Mon, 5 Aug 2024 at 18:05, shveta malik <shveta.malik@gmail.com> wrote:
    > > > >
    > > > > On Mon, Aug 5, 2024 at 11:04 AM vignesh C <vignesh21@gmail.com> wrote:
    > > > > >
    > > > > > On Wed, 31 Jul 2024 at 14:39, shveta malik <shveta.malik@gmail.com> wrote:
    > > > > > >
    > > > > > > On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > > >
    > > > > > > > On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    > > > > > > > >
    > > > > > > > >
    > > > > > > > >
    > > > > > > > > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > > > >>
    > > > > > > > >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > > > >> [...]
    > > > > > > > >> A new catalog table, pg_subscription_seq, has been introduced for
    > > > > > > > >> mapping subscriptions to sequences. Additionally, the sequence LSN
    > > > > > > > >> (Log Sequence Number) is stored, facilitating determination of
    > > > > > > > >> sequence changes occurring before or after the returned sequence
    > > > > > > > >> state.
    > > > > > > > >
    > > > > > > > >
    > > > > > > > > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    > > > > > > > > something.
    > > > > > > >
    > > > > > > > We'll require the lsn because the sequence LSN informs the user that
    > > > > > > > it has been synchronized up to the LSN in pg_subscription_seq. Since
    > > > > > > > we are not supporting incremental sync, the user will be able to
    > > > > > > > identify if he should run refresh sequences or not by checking the lsn
    > > > > > > > of the pg_subscription_seq and the lsn of the sequence(using
    > > > > > > > pg_sequence_state added) in the publisher.
    > > > > > >
    > > > > > > How the user will know from seq's lsn that he needs to run refresh.
    > > > > > > lsn indicates page_lsn and thus the sequence might advance on pub
    > > > > > > without changing lsn and thus lsn may look the same on subscriber even
    > > > > > > though a sequence-refresh is needed. Am I missing something here?
    > > > > >
    > > > > > When a sequence is synchronized to the subscriber, the page LSN of the
    > > > > > sequence from the publisher is also retrieved and stored in
    > > > > > pg_subscriber_rel as shown below:
    > > > > > --- Publisher page lsn
    > > > > > publisher=# select pg_sequence_state('seq1');
    > > > > >  pg_sequence_state
    > > > > > --------------------
    > > > > >  (0/1510E38,65,1,t)
    > > > > > (1 row)
    > > > > >
    > > > > > --- Subscriber stores the publisher's page lsn for the sequence
    > > > > > subscriber=# select * from pg_subscription_rel where srrelid = 16384;
    > > > > >  srsubid | srrelid | srsubstate | srsublsn
    > > > > > ---------+---------+------------+-----------
    > > > > >    16389 |   16384 | r          | 0/1510E38
    > > > > > (1 row)
    > > > > >
    > > > > > If changes are made to the sequence, such as performing many nextvals,
    > > > > > the page LSN will be updated. Currently the sequence values are
    > > > > > prefetched for SEQ_LOG_VALS 32, so the lsn will not get updated for
    > > > > > the prefetched values, once the prefetched values are consumed the lsn
    > > > > > will get updated.
    > > > > > For example:
    > > > > > --- Updated LSN on the publisher (old lsn - 0/1510E38, new lsn - 0/1558CA8)
    > > > > > publisher=# select pg_sequence_state('seq1');
    > > > > >   pg_sequence_state
    > > > > > ----------------------
    > > > > >  (0/1558CA8,143,22,t)
    > > > > > (1 row)
    > > > > >
    > > > > > The user can then compare this updated value with the sequence's LSN
    > > > > > in pg_subscription_rel to determine when to re-synchronize the
    > > > > > sequence.
    > > > >
    > > > > Thanks for the details. But I was referring to the case where we are
    > > > > in between pre-fetched values on publisher (say at 25th value), while
    > > > > on subscriber we are slightly behind (say at 15th value), but page-lsn
    > > > > will be the same on both. Since the subscriber is behind, a
    > > > > sequence-refresh is needed on sub, but by looking at lsn (which is
    > > > > same), one can not say that for sure.  Let me know if I have
    > > > > misunderstood it.
    > > >
    > > > Yes, at present, if the value is within the pre-fetched range, we
    > > > cannot distinguish it solely using the page_lsn.
    > > >
    > >
    > > This makes sense to me.
    > >
    > > >
    > > > However, the
    > > > pg_sequence_state function also provides last_value and log_cnt, which
    > > > can be used to handle these specific cases.
    > > >
    > >
    > > BTW, can we document all these steps for users to know when to refresh
    > > the sequences, if not already documented?
    >
    > This has been documented in the v20240807 version attached at [1].
    > [1] - https://www.postgresql.org/message-id/CALDaNm01Z6Oo9osGMFTOoyTR1kVoyh1rEvZ%2B6uJn-ZymV%3D0dbQ%40mail.gmail.com
    >
    
    Vignesh, I looked at the patch dated 240808, but I could not  find
    these steps. Are you referring to the section ' Examples:
    Synchronizing Sequences Between Publisher and Subscriber' in doc
    patch004? If not, please point me to the concerned section.
    
    thanks
    Shveta
    
    
    
    
  135. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-09T07:10:08Z

    Hi Vignesh, here are my review comments for the sequences docs patch
    v20240808-0004.
    
    ======
    doc/src/sgml/logical-replication.sgml
    
    The new section content looked good.
    
    Just some nitpicks including:
    - renamed the section "Replicating Sequences"
    - added missing mention about how to publish sequences
    - rearranged the subscription commands into a more readable list
    - some sect2 titles were very long; I shortened them.
    - added <warning> markup for the sequence definition advice
    - other minor rewording and typo fixes
    
    ~
    
    1.
    IMO the "Caveats" section can be removed.
    - the advice to avoid changing the sequence definition is already
    given earlier in the "Sequence Definition Mismatches" section
    - the limitation of "incremental synchronization" is already stated in
    the logical replication "Limitations" section
    - (FYI, I removed it already in my nitpicks attachment)
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    nitpick - I reversed the paragraphs to keep the references in a natural order.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    On Fri, Aug 9, 2024 at 1:52 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 8 Aug 2024 at 08:30, Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > Hi Vignesh, Here are my v20240807-0003 review comments.
    > >
    > > 2a.
    > > The paragraph starts by saying "Sequence data is not replicated.". It
    > > seems wrong now. Doesn't that need rewording or removing?
    >
    > Changed it to incremental sequence changes.
    >
    > > ~
    > >
    > > 2b.
    > > Should the info "If, however, some kind of switchover or failover..."
    > > be mentioned in the "Logical Replication Failover" section [2],
    > > instead of here?
    >
    > I think mentioning this here is appropriate. The other section focuses
    > more on how logical replication can proceed with a new primary. Once
    > the logical replication setup is complete, sequences can be refreshed
    > at any time.
    >
    > Rest of the comments  are fixed,  the attached v20240808 version patch
    > has the changes for the same.
    >
    > Regards,
    > Vignesh
    
  136. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-09T13:12:41Z

    On Thu, 8 Aug 2024 at 12:21, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Wed, Aug 7, 2024 at 1:45 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > >
    > > The remaining comments have been addressed, and the changes are
    > > included in the attached v20240807 version patch.
    >
    > Thanks for addressing the comment. Please find few comments for v20240807 :
    >
    > patch003:
    > 2)
    >
    >  * The page_lsn allows the user to determine if the sequence has been updated
    >  * since the last synchronization with the subscriber. This is done by
    >  * comparing the current page_lsn with the value stored in pg_subscription_rel
    >  * from the last synchronization.
    >  */
    > Datum
    > pg_sequence_state(PG_FUNCTION_ARGS)
    >
    > --This information is still incomplete. Maybe we should mention the
    > other attribute name as well which helps to determine this.
    
    I have removed this comment now as suggesting that users use
    pg_sequence_state and sequence when page_lsn seems complex, the same
    can be achieved by comparing the sequence values from a single
    statement instead of a couple of statements. Peter had felt this would
    be easier based on comment 3c at [1].
    
    > 5)
    > IIUC, sequencesync_failure_time is changed by multiple processes.
    > Seq-sync worker sets it before exiting on failure, while apply worker
    > resets it. Also, the applied worker reads it at a few places. Shall it
    > be accessed using LogicalRepWorkerLock?
    
    If sequenceApply worker is already running, apply worker will not
    access sequencesync_failure_time. Only if sequence sync worker is not
    running apply worker will access sequencesync_failure_time in the
    below code. I feel no need to use LogicalRepWorkerLock in this case.
    
    ...
    syncworker = logicalrep_worker_find(MyLogicalRepWorker->subid,
    InvalidOid, WORKERTYPE_SEQUENCESYNC,
    true);
    if (syncworker)
    {
    /* Now safe to release the LWLock */
    LWLockRelease(LogicalRepWorkerLock);
    break;
    }
    
    /*
    * Count running sync workers for this subscription, while we have the
    * lock.
    */
    nsyncworkers = logicalrep_sync_worker_count(MyLogicalRepWorker->subid);
    
    /* Now safe to release the LWLock */
    LWLockRelease(LogicalRepWorkerLock);
    
    /*
    * If there are free sync worker slot(s), start a new sequence sync
    * worker, and break from the loop.
    */
    if (nsyncworkers < max_sync_workers_per_subscription)
    {
    TimestampTz now = GetCurrentTimestamp();
    
    if (!MyLogicalRepWorker->sequencesync_failure_time ||
    TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
       now, wal_retrieve_retry_interval))
    {
    MyLogicalRepWorker->sequencesync_failure_time = 0;
    
    logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    MyLogicalRepWorker->dbid,
    MySubscription->oid,
    MySubscription->name,
    MyLogicalRepWorker->userid,
    InvalidOid,
    DSM_HANDLE_INVALID);
    break;
    }
    }
    ...
    
    > 6)
    > process_syncing_sequences_for_apply():
    >
    > --I feel MyLogicalRepWorker->sequencesync_failure_time should be reset
    > to 0 after we are sure that logicalrep_worker_launch() has launched
    > the worker without any error. But not sure what could be the clean way
    > to do it? If we move it after logicalrep_worker_launch() call, there
    > are chances that seq-sync worker has started and failed already and
    > has set this failure time which will then be mistakenly reset by apply
    > worker. Also moving it inside logicalrep_worker_launch() does not seem
    > a good way.
    
    I felt we can keep it in the existing way to keep it consistent with
    table sync worker restart like in process_syncing_tables_for_apply.
    
    The rest of the comments are fixed.  The rest of the comments are
    fixed in the v20240809 version patch attached.
    
    [1] - https://www.postgresql.org/message-id/CAHut%2BPvaq%3D0xsDWdVQ-kdjRa8Az%2BvgiMFTvT2E2nR3N-47TO8A%40mail.gmail.com
    
    Regards,
    Vignesh
    
  137. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-09T13:18:04Z

    On Fri, 9 Aug 2024 at 12:13, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Wed, Aug 7, 2024 at 2:00 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Wed, 7 Aug 2024 at 08:09, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Tue, Aug 6, 2024 at 5:13 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > On Mon, 5 Aug 2024 at 18:05, shveta malik <shveta.malik@gmail.com> wrote:
    > > > > >
    > > > > > On Mon, Aug 5, 2024 at 11:04 AM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > >
    > > > > > > On Wed, 31 Jul 2024 at 14:39, shveta malik <shveta.malik@gmail.com> wrote:
    > > > > > > >
    > > > > > > > On Mon, Jun 10, 2024 at 5:00 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > > > >
    > > > > > > > > On Mon, 10 Jun 2024 at 12:24, Amul Sul <sulamul@gmail.com> wrote:
    > > > > > > > > >
    > > > > > > > > >
    > > > > > > > > >
    > > > > > > > > > On Sat, Jun 8, 2024 at 6:43 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > > > > >>
    > > > > > > > > >> On Wed, 5 Jun 2024 at 14:11, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > > > > >> [...]
    > > > > > > > > >> A new catalog table, pg_subscription_seq, has been introduced for
    > > > > > > > > >> mapping subscriptions to sequences. Additionally, the sequence LSN
    > > > > > > > > >> (Log Sequence Number) is stored, facilitating determination of
    > > > > > > > > >> sequence changes occurring before or after the returned sequence
    > > > > > > > > >> state.
    > > > > > > > > >
    > > > > > > > > >
    > > > > > > > > > Can't it be done using pg_depend? It seems a bit excessive unless I'm missing
    > > > > > > > > > something.
    > > > > > > > >
    > > > > > > > > We'll require the lsn because the sequence LSN informs the user that
    > > > > > > > > it has been synchronized up to the LSN in pg_subscription_seq. Since
    > > > > > > > > we are not supporting incremental sync, the user will be able to
    > > > > > > > > identify if he should run refresh sequences or not by checking the lsn
    > > > > > > > > of the pg_subscription_seq and the lsn of the sequence(using
    > > > > > > > > pg_sequence_state added) in the publisher.
    > > > > > > >
    > > > > > > > How the user will know from seq's lsn that he needs to run refresh.
    > > > > > > > lsn indicates page_lsn and thus the sequence might advance on pub
    > > > > > > > without changing lsn and thus lsn may look the same on subscriber even
    > > > > > > > though a sequence-refresh is needed. Am I missing something here?
    > > > > > >
    > > > > > > When a sequence is synchronized to the subscriber, the page LSN of the
    > > > > > > sequence from the publisher is also retrieved and stored in
    > > > > > > pg_subscriber_rel as shown below:
    > > > > > > --- Publisher page lsn
    > > > > > > publisher=# select pg_sequence_state('seq1');
    > > > > > >  pg_sequence_state
    > > > > > > --------------------
    > > > > > >  (0/1510E38,65,1,t)
    > > > > > > (1 row)
    > > > > > >
    > > > > > > --- Subscriber stores the publisher's page lsn for the sequence
    > > > > > > subscriber=# select * from pg_subscription_rel where srrelid = 16384;
    > > > > > >  srsubid | srrelid | srsubstate | srsublsn
    > > > > > > ---------+---------+------------+-----------
    > > > > > >    16389 |   16384 | r          | 0/1510E38
    > > > > > > (1 row)
    > > > > > >
    > > > > > > If changes are made to the sequence, such as performing many nextvals,
    > > > > > > the page LSN will be updated. Currently the sequence values are
    > > > > > > prefetched for SEQ_LOG_VALS 32, so the lsn will not get updated for
    > > > > > > the prefetched values, once the prefetched values are consumed the lsn
    > > > > > > will get updated.
    > > > > > > For example:
    > > > > > > --- Updated LSN on the publisher (old lsn - 0/1510E38, new lsn - 0/1558CA8)
    > > > > > > publisher=# select pg_sequence_state('seq1');
    > > > > > >   pg_sequence_state
    > > > > > > ----------------------
    > > > > > >  (0/1558CA8,143,22,t)
    > > > > > > (1 row)
    > > > > > >
    > > > > > > The user can then compare this updated value with the sequence's LSN
    > > > > > > in pg_subscription_rel to determine when to re-synchronize the
    > > > > > > sequence.
    > > > > >
    > > > > > Thanks for the details. But I was referring to the case where we are
    > > > > > in between pre-fetched values on publisher (say at 25th value), while
    > > > > > on subscriber we are slightly behind (say at 15th value), but page-lsn
    > > > > > will be the same on both. Since the subscriber is behind, a
    > > > > > sequence-refresh is needed on sub, but by looking at lsn (which is
    > > > > > same), one can not say that for sure.  Let me know if I have
    > > > > > misunderstood it.
    > > > >
    > > > > Yes, at present, if the value is within the pre-fetched range, we
    > > > > cannot distinguish it solely using the page_lsn.
    > > > >
    > > >
    > > > This makes sense to me.
    > > >
    > > > >
    > > > > However, the
    > > > > pg_sequence_state function also provides last_value and log_cnt, which
    > > > > can be used to handle these specific cases.
    > > > >
    > > >
    > > > BTW, can we document all these steps for users to know when to refresh
    > > > the sequences, if not already documented?
    > >
    > > This has been documented in the v20240807 version attached at [1].
    > > [1] - https://www.postgresql.org/message-id/CALDaNm01Z6Oo9osGMFTOoyTR1kVoyh1rEvZ%2B6uJn-ZymV%3D0dbQ%40mail.gmail.com
    > >
    >
    > Vignesh, I looked at the patch dated 240808, but I could not  find
    > these steps. Are you referring to the section ' Examples:
    > Synchronizing Sequences Between Publisher and Subscriber' in doc
    > patch004? If not, please point me to the concerned section.
    
    I'm  referring to the "Refreshing Stale Sequences" part in the
    v20240809 version patch attached at [1] which only mentions directly
    comparing the sequence values.. I have removed the reference to
    pg_sequence_state now as suggesting that users use pg_sequence_state
    and sequence when page_lsn seems complex, the same can be achieved by
    comparing the sequence values from a single statement instead of a
    couple of statements. Peter had felt this would be easier based on
    comment 3c at [1].
    
    [1] - https://www.postgresql.org/message-id/CALDaNm0LJCtGoBCO6DFY-RDjR8vxapW3W1f7%3D-LSQx%3DXYjqU%3Dw%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  138. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-09T13:19:16Z

    On Fri, 9 Aug 2024 at 05:51, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh, I reviewed the latest v20240808-0003 patch.
    >
    > Attached are my minor change suggestions.
    
    Thanks, these changes are merged in the v20240809 version posted at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm0LJCtGoBCO6DFY-RDjR8vxapW3W1f7%3D-LSQx%3DXYjqU%3Dw%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  139. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-09T13:21:41Z

    On Fri, 9 Aug 2024 at 12:40, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh, here are my review comments for the sequences docs patch
    > v20240808-0004.
    >
    > ======
    > doc/src/sgml/logical-replication.sgml
    >
    > The new section content looked good.
    >
    > Just some nitpicks including:
    > - renamed the section "Replicating Sequences"
    > - added missing mention about how to publish sequences
    > - rearranged the subscription commands into a more readable list
    > - some sect2 titles were very long; I shortened them.
    > - added <warning> markup for the sequence definition advice
    > - other minor rewording and typo fixes
    
    I have retained the caveats section for now, I will think more and
    remove it if required in the next version.
    
    The rest of the comments are fixed in the v20240809 version patch
    attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm0LJCtGoBCO6DFY-RDjR8vxapW3W1f7%3D-LSQx%3DXYjqU%3Dw%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  140. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-12T03:20:04Z

    Hi Vignesh,
    
    v20240809-0001. No comments.
    v20240809-0002. See below.
    v20240809-0003. See below.
    v20240809-0004. No comments.
    
    //////////
    
    Here are my review comments for patch v20240809-0002.
    
    nit - Tweak wording in new docs example, because a publication only
    publishes the sequences; it doesn't "synchronize" anything.
    
    //////////
    
    Here are my review comments for patch v20240809-0003.
    
    fetch_sequence_list:
    nit - move comment
    nit - minor rewording for parameter WARNING message
    
    ======
    .../replication/logical/sequencesync.c
    src/backend/replication/logical/tablesync.c
    
    1.
    Currently the declaration 'sequence_states_not_ready' list seems
    backwards. IMO it makes more sense for the declaration to be in
    sequencesync.c, and the extern in the tablesync.c. (please also see
    review comment #3 below which might affect this too).
    
    ~~~
    
    2.
     static bool
    -FetchTableStates(bool *started_tx)
    +FetchTableStates(void)
     {
    - static bool has_subrels = false;
    -
    - *started_tx = false;
    + static bool has_subtables = false;
    + bool started_tx = false;
    
    Maybe give the explanation why 'has_subtables' is declared static here.
    
    ~~~
    
    3.
    I am not sure that it was an improvement to move the
    process_syncing_sequences_for_apply() function into the
    sequencesync.c. Calling the sequence code from the tablesync code
    still looks strange. OTOH, I see why you don't want to leave it in
    tablesync.c.
    
    Perhaps it would be better to refactor/move all following functions
    back to the (apply) worker.c instead:
    - process_syncing_relations
    - process_syncing_sequences_for_apply(void)
    - process_syncing_tables_for_apply(void)
    
    Actually, now that there are 2 kinds of 'sync' workers, maybe you
    should introduce a new module (e.g. 'commonsync.c' or
    'syncworker.c...), where you can put functions such as
    process_syncing_relations() plus any other code common to both
    tablesync and sequencesync. That might make more sense then having one
    call to the other.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  141. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-12T04:28:55Z

    Hi Vignesh,
    
    I noticed it is not currently possible (there is no syntax way to do
    it) to ALTER an existing publication so that it will publish
    SEQUENCES.
    
    Isn't that a limitation? Why?
    
    For example,. Why should users be prevented from changing a FOR ALL
    TABLES publication into a FOR ALL TABLES, SEQUENCES one?
    
    Similarly, there are other combinations not possible
    DROP ALL SEQUENCES from a publication that is FOR ALL TABLES, SEQUENCES
    DROP ALL TABLES from a publication that is FOR ALL TABLES, SEQUENCES
    ADD ALL TABLES to a publication that is FOR ALL SEQUENCES
    ...
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  142. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-12T05:09:47Z

    Hi Vignesh,
    
    I found that when 2 subscriptions are both subscribing to a
    publication publishing sequences, an ERROR occurs on refresh.
    
    ======
    
    Publisher:
    ----------
    
    test_pub=# create publication pub1 for all sequences;
    
    Subscriber:
    -----------
    
    test_sub=# create subscription sub1 connection 'dbname=test_pub'
    publication pub1;
    
    test_sub=# create subscription sub2 connection 'dbname=test_pub'
    publication pub1;
    
    test_sub=# alter subscription sub1 refresh publication sequences;
    2024-08-12 15:04:04.947 AEST [7306] LOG:  sequence "public.seq1" of
    subscription "sub1" set to INIT state
    2024-08-12 15:04:04.947 AEST [7306] STATEMENT:  alter subscription
    sub1 refresh publication sequences;
    2024-08-12 15:04:04.947 AEST [7306] LOG:  sequence "public.seq1" of
    subscription "sub1" set to INIT state
    2024-08-12 15:04:04.947 AEST [7306] STATEMENT:  alter subscription
    sub1 refresh publication sequences;
    2024-08-12 15:04:04.947 AEST [7306] ERROR:  tuple already updated by self
    2024-08-12 15:04:04.947 AEST [7306] STATEMENT:  alter subscription
    sub1 refresh publication sequences;
    ERROR:  tuple already updated by self
    
    test_sub=# alter subscription sub2 refresh publication sequences;
    2024-08-12 15:04:30.427 AEST [7306] LOG:  sequence "public.seq1" of
    subscription "sub2" set to INIT state
    2024-08-12 15:04:30.427 AEST [7306] STATEMENT:  alter subscription
    sub2 refresh publication sequences;
    2024-08-12 15:04:30.427 AEST [7306] LOG:  sequence "public.seq1" of
    subscription "sub2" set to INIT state
    2024-08-12 15:04:30.427 AEST [7306] STATEMENT:  alter subscription
    sub2 refresh publication sequences;
    2024-08-12 15:04:30.427 AEST [7306] ERROR:  tuple already updated by self
    2024-08-12 15:04:30.427 AEST [7306] STATEMENT:  alter subscription
    sub2 refresh publication sequences;
    ERROR:  tuple already updated by self
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  143. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-12T13:06:26Z

    On Mon, 12 Aug 2024 at 08:50, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > ~~~
    >
    > 3.
    > I am not sure that it was an improvement to move the
    > process_syncing_sequences_for_apply() function into the
    > sequencesync.c. Calling the sequence code from the tablesync code
    > still looks strange. OTOH, I see why you don't want to leave it in
    > tablesync.c.
    >
    > Perhaps it would be better to refactor/move all following functions
    > back to the (apply) worker.c instead:
    > - process_syncing_relations
    > - process_syncing_sequences_for_apply(void)
    > - process_syncing_tables_for_apply(void)
    >
    > Actually, now that there are 2 kinds of 'sync' workers, maybe you
    > should introduce a new module (e.g. 'commonsync.c' or
    > 'syncworker.c...), where you can put functions such as
    > process_syncing_relations() plus any other code common to both
    > tablesync and sequencesync. That might make more sense then having one
    > call to the other.
    
    I created syncutils.c to consolidate code that supports worker
    synchronization, table synchronization, and sequence synchronization.
    While it may not align exactly with your suggestion, I included
    functions like finish_sync_worker, invalidate_syncing_relation_states,
    FetchRelationStates, and process_syncing_relations in this new file. I
    believe this organization will make the code easier to review.
    
    The rest of the comments are also fixed in the attached v20240812
    version patch attached.
    
    Regards,
    Vignesh
    
  144. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-12T13:07:21Z

    On Mon, 12 Aug 2024 at 10:40, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > I found that when 2 subscriptions are both subscribing to a
    > publication publishing sequences, an ERROR occurs on refresh.
    >
    > ======
    >
    > Publisher:
    > ----------
    >
    > test_pub=# create publication pub1 for all sequences;
    >
    > Subscriber:
    > -----------
    >
    > test_sub=# create subscription sub1 connection 'dbname=test_pub'
    > publication pub1;
    >
    > test_sub=# create subscription sub2 connection 'dbname=test_pub'
    > publication pub1;
    >
    > test_sub=# alter subscription sub1 refresh publication sequences;
    > 2024-08-12 15:04:04.947 AEST [7306] LOG:  sequence "public.seq1" of
    > subscription "sub1" set to INIT state
    > 2024-08-12 15:04:04.947 AEST [7306] STATEMENT:  alter subscription
    > sub1 refresh publication sequences;
    > 2024-08-12 15:04:04.947 AEST [7306] LOG:  sequence "public.seq1" of
    > subscription "sub1" set to INIT state
    > 2024-08-12 15:04:04.947 AEST [7306] STATEMENT:  alter subscription
    > sub1 refresh publication sequences;
    > 2024-08-12 15:04:04.947 AEST [7306] ERROR:  tuple already updated by self
    > 2024-08-12 15:04:04.947 AEST [7306] STATEMENT:  alter subscription
    > sub1 refresh publication sequences;
    > ERROR:  tuple already updated by self
    >
    > test_sub=# alter subscription sub2 refresh publication sequences;
    > 2024-08-12 15:04:30.427 AEST [7306] LOG:  sequence "public.seq1" of
    > subscription "sub2" set to INIT state
    > 2024-08-12 15:04:30.427 AEST [7306] STATEMENT:  alter subscription
    > sub2 refresh publication sequences;
    > 2024-08-12 15:04:30.427 AEST [7306] LOG:  sequence "public.seq1" of
    > subscription "sub2" set to INIT state
    > 2024-08-12 15:04:30.427 AEST [7306] STATEMENT:  alter subscription
    > sub2 refresh publication sequences;
    > 2024-08-12 15:04:30.427 AEST [7306] ERROR:  tuple already updated by self
    > 2024-08-12 15:04:30.427 AEST [7306] STATEMENT:  alter subscription
    > sub2 refresh publication sequences;
    > ERROR:  tuple already updated by self
    
    This issue is fixed in the v20240812 version attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm3hS58W0RTbgsMTk-YvXwt956uabA%3DkYfLGUs3uRNC2Qg%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  145. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-12T13:10:58Z

    On Mon, 12 Aug 2024 at 09:59, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > I noticed it is not currently possible (there is no syntax way to do
    > it) to ALTER an existing publication so that it will publish
    > SEQUENCES.
    >
    > Isn't that a limitation? Why?
    >
    > For example,. Why should users be prevented from changing a FOR ALL
    > TABLES publication into a FOR ALL TABLES, SEQUENCES one?
    >
    > Similarly, there are other combinations not possible
    > DROP ALL SEQUENCES from a publication that is FOR ALL TABLES, SEQUENCES
    > DROP ALL TABLES from a publication that is FOR ALL TABLES, SEQUENCES
    > ADD ALL TABLES to a publication that is FOR ALL SEQUENCES
    
    Yes, this should be addressed. However, I'll defer it until the
    current set of patches is finalized and all comments have been
    resolved.
    
    Regards,
    Vignesh
    
    
    
    
  146. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-13T03:49:26Z

    Hi Vignesh, Here are my review comments for latest v20240812* patchset:
    
    patch v20240812-0001. No comments.
    patch v20240812-0002. Fixed docs.LGTM
    patch v20240812-0003. This is new refactoring. See below.
    patch v20240812-0004. (was 0003). See below.
    patch v20240812-0005. (was 0004). No comments.
    
    //////
    
    patch v20240812-0003.
    
    3.1. GENERAL
    
    Hmm. I am guessing this was provided as a separate patch to aid review
    by showing that existing functions are moved? OTOH you can't really
    judge this patch properly without already knowing details of what will
    come next in the sequencesync. i.e. As a *standalone* patch without
    the sequencesync.c the refactoring doesn't make much sense.
    
    Maybe it is OK later to combine patches 0003 and 0004. Alternatively,
    keep this patch separated but give greater emphasis in the comment
    header to say this patch only exists separately in order to help the
    review.
    
    ======
    Commit message
    
    3.2.
    Reorganized tablesync code to generate a syncutils file which will
    help in sequence synchronization worker code.
    
    ~
    
    "generate" ??
    
    ======
    src/backend/replication/logical/syncutils.c
    
    3.3. "common code" ??
    
    FYI - There are multiple code comments mentioning "common code..."
    which, in the absence of the sequencesync worker (which comes in the
    next patch), have nothing "common" about them at all. Fixing them and
    then fixing them again in the next patch might cause unnecessary code
    churn, but OTOH they aren't correct as-is either. I have left them
    alone for now.
    
    ~
    
    3.4. function names
    
    With the re-shuffling that this patch does, and changing several from
    static to not-static, should the function names remain as they are?
    They look random to me.
    - finish_sync_worker(void)
    - invalidate_syncing_table_states(Datum arg, int cacheid, uint32 hashvalue)
    - FetchTableStates(bool *started_tx)
    - process_syncing_tables(XLogRecPtr current_lsn)
    
    I think using a consistent naming convention would be better. e.g.
    SyncFinishWorker
    SyncInvalidateTableStates
    SyncFetchTableStates
    SyncProcessTables
    
    ~~~
    
    nit - file header comment
    
    ======
    src/backend/replication/logical/tablesync.c
    
    3.5.
    -static void
    +void
     process_syncing_tables_for_sync(XLogRecPtr current_lsn)
    
    -static void
    +void
     process_syncing_tables_for_apply(XLogRecPtr current_lsn)
    
    Since these functions are no longer static should those function names
    be changed to use the CamelCase convention for non-static API?
    
    //////////
    
    patch v20240812-0004.
    
    ======
    src/backend/replication/logical/syncutils.c
    
    nit - file header comment (made same as patch 0003)
    
    ~
    
    FetchRelationStates:
    nit - IIUC sequence states are only INIT -> READY. So the comments in
    this function dont need to specifically talk about sequence INIT
    state.
    
    ======
    src/backend/utils/misc/guc_tables.c
    
    4.1.
      {"max_sync_workers_per_subscription",
      PGC_SIGHUP,
      REPLICATION_SUBSCRIBERS,
    - gettext_noop("Maximum number of table synchronization workers per
    subscription."),
    + gettext_noop("Maximum number of relation synchronization workers per
    subscription."),
      NULL,
      },
    
    I was wondering if "relation synchronization workers" is meaningful to
    the user because that seems like new terminology.
    Maybe it should say "... of table + sequence synchronization workers..."
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  147. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-13T04:03:44Z

    On Mon, Aug 12, 2024 at 11:07 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 12 Aug 2024 at 10:40, Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > Hi Vignesh,
    > >
    > > I found that when 2 subscriptions are both subscribing to a
    > > publication publishing sequences, an ERROR occurs on refresh.
    > >
    > > ======
    > >
    > > Publisher:
    > > ----------
    > >
    > > test_pub=# create publication pub1 for all sequences;
    > >
    > > Subscriber:
    > > -----------
    > >
    > > test_sub=# create subscription sub1 connection 'dbname=test_pub'
    > > publication pub1;
    > >
    > > test_sub=# create subscription sub2 connection 'dbname=test_pub'
    > > publication pub1;
    > >
    > > test_sub=# alter subscription sub1 refresh publication sequences;
    > > 2024-08-12 15:04:04.947 AEST [7306] LOG:  sequence "public.seq1" of
    > > subscription "sub1" set to INIT state
    > > 2024-08-12 15:04:04.947 AEST [7306] STATEMENT:  alter subscription
    > > sub1 refresh publication sequences;
    > > 2024-08-12 15:04:04.947 AEST [7306] LOG:  sequence "public.seq1" of
    > > subscription "sub1" set to INIT state
    > > 2024-08-12 15:04:04.947 AEST [7306] STATEMENT:  alter subscription
    > > sub1 refresh publication sequences;
    > > 2024-08-12 15:04:04.947 AEST [7306] ERROR:  tuple already updated by self
    > > 2024-08-12 15:04:04.947 AEST [7306] STATEMENT:  alter subscription
    > > sub1 refresh publication sequences;
    > > ERROR:  tuple already updated by self
    > >
    > > test_sub=# alter subscription sub2 refresh publication sequences;
    > > 2024-08-12 15:04:30.427 AEST [7306] LOG:  sequence "public.seq1" of
    > > subscription "sub2" set to INIT state
    > > 2024-08-12 15:04:30.427 AEST [7306] STATEMENT:  alter subscription
    > > sub2 refresh publication sequences;
    > > 2024-08-12 15:04:30.427 AEST [7306] LOG:  sequence "public.seq1" of
    > > subscription "sub2" set to INIT state
    > > 2024-08-12 15:04:30.427 AEST [7306] STATEMENT:  alter subscription
    > > sub2 refresh publication sequences;
    > > 2024-08-12 15:04:30.427 AEST [7306] ERROR:  tuple already updated by self
    > > 2024-08-12 15:04:30.427 AEST [7306] STATEMENT:  alter subscription
    > > sub2 refresh publication sequences;
    > > ERROR:  tuple already updated by self
    >
    > This issue is fixed in the v20240812 version attached at [1].
    > [1] - https://www.postgresql.org/message-id/CALDaNm3hS58W0RTbgsMTk-YvXwt956uabA%3DkYfLGUs3uRNC2Qg%40mail.gmail.com
    >
    
    Yes, I confirmed it is now fixed. Thanks!
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  148. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-13T07:00:53Z

    Hi Vignesh,
    
    I have been using the latest patchset, trying a few things using many
    (1000) sequences.
    
    Here are some observations, plus some suggestions for consideration.
    
    ~~~~~
    
    OBSERVATION #1
    
    When 1000s of sequences are refreshed using REFRESH PUBLICATION
    SEQUENCES the logging is excessive. For example, since there is only
    one sequencesync worker why does it need to broadcast that it is
    "finished" separately for every single sequence. That is giving 1000s
    of lines of logs which don't seem to be of much interest to a user.
    
    ...
    2024-08-13 16:17:04.151 AEST [5002] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0918" has
    finished
    2024-08-13 16:17:04.151 AEST [5002] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0919" has
    finished
    2024-08-13 16:17:04.151 AEST [5002] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0920" has
    finished
    2024-08-13 16:17:04.151 AEST [5002] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0921" has
    finished
    2024-08-13 16:17:04.151 AEST [5002] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0922" has
    finished
    2024-08-13 16:17:04.151 AEST [5002] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0923" has
    finished
    ...
    
    Perhaps just LOG when each "batch" is completed, but the individual
    sequence finished logs can just be DEBUG information?
    
    ~~~~~
    
    OBSERVATION #2
    
    When 1000s of sequences are refreshed (set to INIT) then there are
    1000s of logs like below:
    
    ...
    2024-08-13 16:13:57.873 AEST [10301] LOG:  sequence "public.seq_0698"
    of subscription "sub3" set to INIT state
    2024-08-13 16:13:57.873 AEST [10301] STATEMENT:  alter subscription
    sub3 refresh publication sequences;
    2024-08-13 16:13:57.873 AEST [10301] LOG:  sequence "public.seq_0699"
    of subscription "sub3" set to INIT state
    2024-08-13 16:13:57.873 AEST [10301] STATEMENT:  alter subscription
    sub3 refresh publication sequences;
    2024-08-13 16:13:57.873 AEST [10301] LOG:  sequence "public.seq_0700"
    of subscription "sub3" set to INIT state
    2024-08-13 16:13:57.873 AEST [10301] STATEMENT:  alter subscription
    sub3 refresh publication sequences;
    2024-08-13 16:13:57.873 AEST [10301] LOG:  sequence "public.seq_0701"
    of subscription "sub3" set to INIT state
    2024-08-13 16:13:57.873 AEST [10301] STATEMENT:  alter subscription
    sub3 refresh publication sequences;
    2024-08-13 16:13:57.874 AEST [10301] LOG:  sequence "public.seq_0702"
    of subscription "sub3" set to INIT state
    2024-08-13 16:13:57.874 AEST [10301] STATEMENT:  alter subscription
    sub3 refresh publication sequences;
    ...
    
    I felt that showing the STATEMENT for all of these is overkill. How
    about changing that ereport LOG so it does not emit the statement 1000
    times? Or, maybe you can implement it as a "dynamic" log that emits
    the STATEMENT if there are only a few logs a few times but skips it
    for the next 995 logs.
    
    ~~~~~
    
    OBSERVATION #3
    
    The WARNING about mismatched sequences currently looks like this:
    
    2024-08-13 16:41:45.496 AEST [10301] WARNING:  Parameters differ for
    remote and local sequences "public.seq_0999"
    2024-08-13 16:41:45.496 AEST [10301] HINT:  Alter/Re-create the
    sequence using the same parameter as in remote.
    
    Although you could probably deduce it from nearby logs, I think it
    might be more helpful to also identify the subscription name in this
    WARNING message. Otherwise, if there are many publications the user
    may have no idea where the mismatched "remote" is coming from.
    
    ~~~~
    
    OBSERVATION #4
    
    When 1000s of sequences are refreshed then there are 1000s of
    associated logs. But (given there is only one sequencesync worker)
    those logs are not always the order that I was expecting to see them.
    
    e.g.
    ...
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0885" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0887" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0888" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0889" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0890" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0906" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0566" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0568" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0569" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0570" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0571" has
    finished
    2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    synchronization for subscription "sub3", sequence "seq_0582" has
    finished
    ...
    
    Is there a way to refresh sequences in a more natural (e.g.
    alphabetical) order to make these logs more readable?
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  149. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-13T11:59:49Z

    On Tue, 13 Aug 2024 at 09:19, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > 3.1. GENERAL
    >
    > Hmm. I am guessing this was provided as a separate patch to aid review
    > by showing that existing functions are moved? OTOH you can't really
    > judge this patch properly without already knowing details of what will
    > come next in the sequencesync. i.e. As a *standalone* patch without
    > the sequencesync.c the refactoring doesn't make much sense.
    >
    > Maybe it is OK later to combine patches 0003 and 0004. Alternatively,
    > keep this patch separated but give greater emphasis in the comment
    > header to say this patch only exists separately in order to help the
    > review.
    
    I have kept this patch only to show that this patch as such has no
    code changes. If we move this to the next patch it will be difficult
    for reviewers to know which is new code and which is old code. During
    commit we can merge this with the next one. I felt it is better to add
    it in the commit message instead of comment header so updated the
    commit message.
    
    > ======
    > src/backend/replication/logical/syncutils.c
    >
    > 3.3. "common code" ??
    >
    > FYI - There are multiple code comments mentioning "common code..."
    > which, in the absence of the sequencesync worker (which comes in the
    > next patch), have nothing "common" about them at all. Fixing them and
    > then fixing them again in the next patch might cause unnecessary code
    > churn, but OTOH they aren't correct as-is either. I have left them
    > alone for now.
    
    We can ignore this as this will get merged to the next one. If you
    have any comments you can give it on top of the next(0004) patch.
    
    > ~
    >
    > 3.4. function names
    >
    > With the re-shuffling that this patch does, and changing several from
    > static to not-static, should the function names remain as they are?
    > They look random to me.
    > - finish_sync_worker(void)
    > - invalidate_syncing_table_states(Datum arg, int cacheid, uint32 hashvalue)
    > - FetchTableStates(bool *started_tx)
    > - process_syncing_tables(XLogRecPtr current_lsn)
    >
    > I think using a consistent naming convention would be better. e.g.
    > SyncFinishWorker
    > SyncInvalidateTableStates
    > SyncFetchTableStates
    > SyncProcessTables
    
    One advantage with keeping the existing names the same wherever
    possible will help while merging the changes to back-branches. So I'm
    not making this change.
    
    > ~~~
    >
    > nit - file header comment
    >
    > ======
    > src/backend/replication/logical/tablesync.c
    >
    > 3.5.
    > -static void
    > +void
    >  process_syncing_tables_for_sync(XLogRecPtr current_lsn)
    >
    > -static void
    > +void
    >  process_syncing_tables_for_apply(XLogRecPtr current_lsn)
    >
    > Since these functions are no longer static should those function names
    > be changed to use the CamelCase convention for non-static API?
    
    One advantage with keeping the existing names the same wherever
    possible will help while merging the changes to back-branches. So I'm
    not making this change.
    
    The rest of the comments were fixed, the attached v20240813 has the
    changes for the same.
    
    Regards,
    Vignesh
    
  150. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-13T12:03:42Z

    On Tue, 13 Aug 2024 at 12:31, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > OBSERVATION #2
    >
    > When 1000s of sequences are refreshed (set to INIT) then there are
    > 1000s of logs like below:
    >
    > ...
    > 2024-08-13 16:13:57.873 AEST [10301] LOG:  sequence "public.seq_0698"
    > of subscription "sub3" set to INIT state
    > 2024-08-13 16:13:57.873 AEST [10301] STATEMENT:  alter subscription
    > sub3 refresh publication sequences;
    > 2024-08-13 16:13:57.873 AEST [10301] LOG:  sequence "public.seq_0699"
    > of subscription "sub3" set to INIT state
    > 2024-08-13 16:13:57.873 AEST [10301] STATEMENT:  alter subscription
    > sub3 refresh publication sequences;
    > 2024-08-13 16:13:57.873 AEST [10301] LOG:  sequence "public.seq_0700"
    > of subscription "sub3" set to INIT state
    > 2024-08-13 16:13:57.873 AEST [10301] STATEMENT:  alter subscription
    > sub3 refresh publication sequences;
    > 2024-08-13 16:13:57.873 AEST [10301] LOG:  sequence "public.seq_0701"
    > of subscription "sub3" set to INIT state
    > 2024-08-13 16:13:57.873 AEST [10301] STATEMENT:  alter subscription
    > sub3 refresh publication sequences;
    > 2024-08-13 16:13:57.874 AEST [10301] LOG:  sequence "public.seq_0702"
    > of subscription "sub3" set to INIT state
    > 2024-08-13 16:13:57.874 AEST [10301] STATEMENT:  alter subscription
    > sub3 refresh publication sequences;
    > ...
    >
    > I felt that showing the STATEMENT for all of these is overkill. How
    > about changing that ereport LOG so it does not emit the statement 1000
    > times? Or, maybe you can implement it as a "dynamic" log that emits
    > the STATEMENT if there are only a few logs a few times but skips it
    > for the next 995 logs.
    
    I have changed it to debug1 log level how we do for tables, so this
    will not appear for  default log level
    
    >
    > OBSERVATION #4
    >
    > When 1000s of sequences are refreshed then there are 1000s of
    > associated logs. But (given there is only one sequencesync worker)
    > those logs are not always the order that I was expecting to see them.
    >
    > e.g.
    > ...
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0885" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0887" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0888" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0889" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0890" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0906" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0566" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0568" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0569" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0570" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0571" has
    > finished
    > 2024-08-13 16:41:47.436 AEST [11735] LOG:  logical replication
    > synchronization for subscription "sub3", sequence "seq_0582" has
    > finished
    > ...
    >
    > Is there a way to refresh sequences in a more natural (e.g.
    > alphabetical) order to make these logs more readable?
    
    I felt this is ok, no need to order it as it can easily be done using
    some scripts if required from logs.
    
    The rest of the issues were fixed, the v20240813 version patch
    attached at [1] has the changes for the same.
    [1] - https://www.postgresql.org/message-id/CALDaNm1Nr_n9SBB52L8A10Txyb4nqGJWfHUapwzM5BopvjMhjA%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  151. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-14T00:34:01Z

    On Tue, Aug 13, 2024 at 10:00 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 13 Aug 2024 at 09:19, Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > 3.1. GENERAL
    > >
    > > Hmm. I am guessing this was provided as a separate patch to aid review
    > > by showing that existing functions are moved? OTOH you can't really
    > > judge this patch properly without already knowing details of what will
    > > come next in the sequencesync. i.e. As a *standalone* patch without
    > > the sequencesync.c the refactoring doesn't make much sense.
    > >
    > > Maybe it is OK later to combine patches 0003 and 0004. Alternatively,
    > > keep this patch separated but give greater emphasis in the comment
    > > header to say this patch only exists separately in order to help the
    > > review.
    >
    > I have kept this patch only to show that this patch as such has no
    > code changes. If we move this to the next patch it will be difficult
    > for reviewers to know which is new code and which is old code. During
    > commit we can merge this with the next one. I felt it is better to add
    > it in the commit message instead of comment header so updated the
    > commit message.
    >
    
    Yes, I wrote "comment header" but it was a typo; I meant "commit
    header". What you did looks good now. Thanks.
    
    > > ~
    > >
    > > 3.4. function names
    > >
    > > With the re-shuffling that this patch does, and changing several from
    > > static to not-static, should the function names remain as they are?
    > > They look random to me.
    > > - finish_sync_worker(void)
    > > - invalidate_syncing_table_states(Datum arg, int cacheid, uint32 hashvalue)
    > > - FetchTableStates(bool *started_tx)
    > > - process_syncing_tables(XLogRecPtr current_lsn)
    > >
    > > I think using a consistent naming convention would be better. e.g.
    > > SyncFinishWorker
    > > SyncInvalidateTableStates
    > > SyncFetchTableStates
    > > SyncProcessTables
    >
    > One advantage with keeping the existing names the same wherever
    > possible will help while merging the changes to back-branches. So I'm
    > not making this change.
    >
    
    According to my understanding, the logical replication code tries to
    maintain name conventions for static functions (snake_case) and for
    non-static functions (CamelCase) as an aid for code readability. I
    think we should either do our best to abide by those conventions, or
    we might as well just forget them and have a naming free-for-all.
    Since the new syncutils.c module is being introduced by this patch, my
    guess is that any future merging to back-branches will be affected
    regardless. IMO this is an ideal opportunity to try to nudge the
    function names in the right direction. YMMV.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  152. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-14T03:09:07Z

    Hi Vignesh, Here are my review comments for the latest patchset:
    
    Patch v20240813-0001. No comments
    Patch v20240813-0002. No comments
    Patch v20240813-0003. No comments
    Patch v20240813-0004. See below
    Patch v20240813-0005. No comments
    
    //////
    
    Patch v20240813-0004
    
    ======
    src/backend/catalog/pg_subscription.
    
    GetSubscriptionRelations:
    nit - modify a condition for readability
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    fetch_sequence_list:
    nit - changed the WARNING message. /parameters differ
    between.../parameters differ for.../ (FYI, Chat-GPT agrees that 2nd
    way is more correct)
    nit - other minor changes to the message and hint
    
    ======
    .../replication/logical/sequencesync.c
    
    1. LogicalRepSyncSequences
    
    + ereport(DEBUG1,
    + errmsg("logical replication synchronization for subscription \"%s\",
    sequence \"%s\" has finished",
    +    get_subscription_name(subid, false), get_rel_name(done_seq->relid)));
    
    DEBUG logs should use errmsg_internal. (fixed also nitpicks attachment).
    
    ~
    
    nit - minor change to the log message counting the batched sequences
    
    ~~~
    
    process_syncing_sequences_for_apply:
    nit - /sequence sync worker/seqeuencesync worker/
    
    ======
    src/backend/utils/misc/guc_tables.c
    
    nit - /max workers/maximum number of workers/ (for consistency because
    all other GUCs are verbose like this; nothing just says "max".)
    
    ======
    src/test/subscription/t/034_sequences.pl
    
    nit - adjust the expected WARNING message (which was modified above)
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  153. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-14T13:06:11Z

    On Wed, 14 Aug 2024 at 08:39, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh, Here are my review comments for the latest patchset:
    >
    > Patch v20240813-0001. No comments
    > Patch v20240813-0002. No comments
    > Patch v20240813-0003. No comments
    > Patch v20240813-0004. See below
    > Patch v20240813-0005. No comments
    >
    > //////
    >
    > Patch v20240813-0004
    >
    
    The comments have been addressed, and the patch also resolves a
    limitation where sequence parameter changes between creating or
    altering a subscription and sequence synchronization worker syncing
    were not detected and reported to the user. This issue is now handled
    by retrieving both the sequence value and its properties in a single
    SELECT statement. The corresponding documentation also was updated.
    
    The attached  v20240814 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  154. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-15T06:27:01Z

    Hi Vignesh, I have reviewed your latest patchset:
    
    v20240814-0001. No comments
    v20240814-0002. No comments
    v20240814-0003. No comments
    v20240814-0004. See below
    v20240814-0005. No comments
    
    //////
    
    v20240814-0004.
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    CreateSubscription:
    nit - XXX comments
    
    AlterSubscription_refresh:
    nit - unnecessary parens in ereport
    
    AlterSubscription:
    nit - unnecessary parens in ereport
    
    fetch_sequence_list:
    nit - unnecessary parens in ereport
    
    ======
    .../replication/logical/sequencesync.c
    
    1. fetch_remote_sequence_data
    
    + * Returns:
    + * - TRUE if there are discrepancies between the sequence parameters in
    + *   the publisher and subscriber.
    + * - FALSE if the parameters match.
    + */
    +static bool
    +fetch_remote_sequence_data(WalReceiverConn *conn, Oid relid, Oid remoteid,
    +    char *nspname, char *relname, int64 *log_cnt,
    +    bool *is_called, XLogRecPtr *page_lsn,
    +    int64 *last_value)
    
    IMO it is more natural to return TRUE for good results and FALSE for
    bad ones. (FYI, I have implemented this reversal in the nitpicks
    attachment).
    
    ~
    
    nit - swapped columns seqmin and seqmax in the SQL to fetch them in
    the natural order
    nit - unnecessary parens in ereport
    
    ~~~
    
    copy_sequence:
    nit - update function comment to document the output parameter
    nit - Assert that *sequence_mismatch is false on entry to this function
    nit - tweak wrapping and add \n in the SQL
    nit - unnecessary parens in ereport
    
    report_sequence_mismatch:
    nit - modify function comment
    nit - function name changed
    /report_sequence_mismatch/report_mismatched_sequences/ (now plural
    (and more like the other one)
    
    append_mismatched_sequences:
    nit - param name /rel/seqrel/
    
    ~~~
    
    2. LogicalRepSyncSequences:
    + Relation sequence_rel;
    + XLogRecPtr sequence_lsn;
    + bool sequence_mismatch;
    
    The 'sequence_mismatch' variable must be initialized false, otherwise
    we cannot trust it gets assigned.
    
    ~
    
    LogicalRepSyncSequences:
    nit - unnecessary parens in ereport
    nit - move the for-loop variable declaration
    nit - remove a blank line
    
    process_syncing_sequences_for_apply:
    nit - variable declaration indent
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  155. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-15T07:38:53Z

    On Thu, 15 Aug 2024 at 11:57, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh, I have reviewed your latest patchset:
    >
    > v20240814-0001. No comments
    > v20240814-0002. No comments
    > v20240814-0003. No comments
    > v20240814-0004. See below
    > v20240814-0005. No comments
    >
    > //////
    >
    > v20240814-0004.
    
    These comments are addressed in the v20240815 version patch attached.
    
    Regards,
    Vignesh
    
  156. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-16T04:55:56Z

    Hi Vignesh. I looked at the latest v20240815* patch set.
    
    I have only the following few comments for patch v20240815-0004, below.
    
    ======
    Commit message.
    
    Please see the attachment for some suggested updates.
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    CreateSubscription:
    nit - fix wording in one of the XXX comments
    
    ======
    .../replication/logical/sequencesync.c
    
    report_mismatched_sequences:
    nit - param name /warning_sequences/mismatched_seqs/
    
    append_mismatched_sequences:
    nit - param name /warning_sequences/mismatched_seqs/
    
    LogicalRepSyncSequences:
    nit - var name /warning_sequences/mismatched_seqs/
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  157. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-16T05:38:28Z

    On Fri, 16 Aug 2024 at 10:26, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh. I looked at the latest v20240815* patch set.
    >
    > I have only the following few comments for patch v20240815-0004, below.
    
    Thanks, these are handled in the v20240816 version patch attached.
    
    Regards,
    Vignesh
    
  158. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-17T15:10:51Z

    On Fri, 16 Aug 2024 at 11:08, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 16 Aug 2024 at 10:26, Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > Hi Vignesh. I looked at the latest v20240815* patch set.
    > >
    > > I have only the following few comments for patch v20240815-0004, below.
    >
    > Thanks, these are handled in the v20240816 version patch attached.
    
    CFBot reported one warning with the patch, here is an updated patch
    for the same.
    
    Regards,
    Vignesh
    
  159. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-19T02:16:53Z

    Here are my review comments for the latest patchset
    
    v20240817-0001. No changes. No comments.
    v20240817-0002. No changes. No comments.
    v20240817-0003. See below.
    v20240817-0004. See below.
    v20240817-0005. No changes. No comments.
    
    //////
    
    v20240817-0003 and 0004.
    
    (This is a repeat of the same comment as in previous reviews, but lots
    more functions seem affected now)
    
    IIUC, the LR code tries to follow function naming conventions (e.g.
    CamelCase/snake_case for exposed/static functions respectively),
    intended to make the code more readable. But, this only works if the
    conventions are followed.
    
    Now, patches 0003 and 0004 are shuffling more and more functions
    between modules while changing them from static to non-static (or vice
    versa). So, the function name conventions are being violated many
    times. IMO these functions ought to be renamed according to their new
    modifiers to avoid the confusion caused by ignoring the name
    conventions.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  160. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-19T13:08:17Z

    On Mon, 19 Aug 2024 at 07:47, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Here are my review comments for the latest patchset
    >
    > v20240817-0001. No changes. No comments.
    > v20240817-0002. No changes. No comments.
    > v20240817-0003. See below.
    > v20240817-0004. See below.
    > v20240817-0005. No changes. No comments.
    >
    > //////
    >
    > v20240817-0003 and 0004.
    >
    > (This is a repeat of the same comment as in previous reviews, but lots
    > more functions seem affected now)
    >
    > IIUC, the LR code tries to follow function naming conventions (e.g.
    > CamelCase/snake_case for exposed/static functions respectively),
    > intended to make the code more readable. But, this only works if the
    > conventions are followed.
    >
    > Now, patches 0003 and 0004 are shuffling more and more functions
    > between modules while changing them from static to non-static (or vice
    > versa). So, the function name conventions are being violated many
    > times. IMO these functions ought to be renamed according to their new
    > modifiers to avoid the confusion caused by ignoring the name
    > conventions.
    
    I have handled these in the v20240819 version patch attached.
    
    Regards,
    Vignesh
    
  161. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-20T01:56:52Z

    Hi Vignesh, Here are my review comments for the latest patchset
    
    v20240819-0001. No changes. No comments.
    v20240819-0002. No changes. No comments.
    v20240819-0003. See below.
    v20240819-0004. See below.
    v20240819-0005. No changes. No comments.
    
    ///////////////////////
    
    PATCH v20240819-0003
    
    ======
    src/backend/replication/logical/syncutils.c
    
    3.1.
    +typedef enum
    +{
    + SYNC_RELATION_STATE_NEEDS_REBUILD,
    + SYNC_RELATION_STATE_REBUILD_STARTED,
    + SYNC_RELATION_STATE_VALID,
    +} SyncingRelationsState;
    +
    +static SyncingRelationsState relation_states_validity =
    SYNC_RELATION_STATE_NEEDS_REBUILD;
    
    There is some muddle of singular/plural names here. The
    typedef/values/var should all match:
    
    e.g. It could be like:
    SYNC_RELATION_STATE_xxx --> SYNC_RELATION_STATES_xxx
    SyncingRelationsState --> SyncRelationStates
    
    But, a more radical change might be better.
    
    typedef enum
    {
    RELATION_STATES_SYNC_NEEDED,
    RELATION_STATES_SYNC_STARTED,
    RELATION_STATES_SYNCED,
    } SyncRelationStates;
    
    ~~~
    
    3.2. GENERAL refactoring
    
    I don't think all of the functions moved into syncutil.c truly belong there.
    
    This new module was introduced to be for common/util functions for
    tablesync and sequencesync, but with each patchset, it has been
    sucking in more and more functions that maybe do not quite belong
    here.
    
    For example, AFAIK these below have logic that is *solely* for TABLES
    (not for SEQUENCES). Perhaps it was convenient to dump them here
    because they are statically called, but I felt they still logically
    belong in tablesync.c:
    - process_syncing_tables_for_sync(XLogRecPtr current_lsn)
    - process_syncing_tables_for_apply(XLogRecPtr current_lsn)
    - AllTablesyncsReady(void)
    
    ~~~
    
    3.3.
    +static bool
    +FetchRelationStates(bool *started_tx)
    +{
    
    If this function can remain static then the name should change to be
    like fetch_table_states, right?
    
    ======
    src/include/replication/worker_internal.h
    
    3.4.
    +extern bool wait_for_relation_state_change(Oid relid, char expected_state);
    
    If this previously static function will be exposed now (it may not
    need to be if some other functions are returned tablesync.c) then the
    function name should also be changed, right?
    
    ////////////////////////
    
    PATCH v20240819-0004
    
    ======
    src/backend/replication/logical/syncutils.c
    
    4.1 GENERAL refactoring
    
    (this is similar to review comment #3.2 above)
    
    Functions like below have logic that is *solely* for SEQUENCES (not
    for TABLES). I felt they logically belong in sequencesync.c, not here.
    - process_syncing_sequences_for_apply(void)
    
    ~~~
    
    FetchRelationStates:
    nit - the comment change about "not-READY tables" (instead of
    relations) should be already in patch 0003.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  162. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-20T07:44:00Z

    On Tue, 20 Aug 2024 at 07:27, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh, Here are my review comments for the latest patchset
    >
    > v20240819-0001. No changes. No comments.
    > v20240819-0002. No changes. No comments.
    > v20240819-0003. See below.
    > v20240819-0004. See below.
    > v20240819-0005. No changes. No comments.
    >
    
    These comments are handled in the v20240820 version patch attached.
    
    Regards,
    Vignesh
    
  163. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-08-21T03:02:55Z

    Hi Vignesh, Here are my only review comments for the latest patch set.
    
    v20240820-0003.
    
    nit - missing period for comment in FetchRelationStates
    nit - typo in function name 'ProcessSyncingTablesFoSync'
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  164. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-08-21T06:24:28Z

    On Wed, 21 Aug 2024 at 08:33, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh, Here are my only review comments for the latest patch set.
    
    Thanks, these issues have been addressed in the updated version.
    Additionally, I have fixed the pgindent problems that were reported
    and included another advantage of this design in the file header of
    the sequencesync file.
    
    Regards,
    Vignesh
    
  165. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-09-20T04:06:44Z

    On Wed, 21 Aug 2024 at 11:54, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 21 Aug 2024 at 08:33, Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > Hi Vignesh, Here are my only review comments for the latest patch set.
    >
    > Thanks, these issues have been addressed in the updated version.
    > Additionally, I have fixed the pgindent problems that were reported
    > and included another advantage of this design in the file header of
    > the sequencesync file.
    
    The patch was not applied on top of head, here is a rebased version of
    the patches.
    I have also removed an invalidation which was  not required for
    sequences and a typo.
    
    Regards,
    Vignesh
    
  166. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-09-26T05:37:25Z

    On Fri, Sep 20, 2024 at 9:36 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 21 Aug 2024 at 11:54, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Wed, 21 Aug 2024 at 08:33, Peter Smith <smithpb2250@gmail.com> wrote:
    > > >
    > > > Hi Vignesh, Here are my only review comments for the latest patch set.
    > >
    > > Thanks, these issues have been addressed in the updated version.
    > > Additionally, I have fixed the pgindent problems that were reported
    > > and included another advantage of this design in the file header of
    > > the sequencesync file.
    >
    > The patch was not applied on top of head, here is a rebased version of
    > the patches.
    > I have also removed an invalidation which was  not required for
    > sequences and a typo.
    >
    
    Thank You for the patches. I would like to understand srsublsn and
    page_lsn more. Please see the scenario below:
    
    I have a sequence:
    CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    
    After refresh on sub:
    postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    ALTER SUBSCRIPTION
    
    postgres=# select * from pg_subscription_rel;
     srsubid | srrelid | srsubstate | srsublsn
    ---------+---------+------------+-----------
       16385 |   16384 | r          | 0/152F380 -->pub's page_lsn
    
    
    postgres=# select * from pg_sequence_state('myseq0');
     page_lsn  | last_value | log_cnt | is_called
    -----------+------------+---------+-----------
     0/152D830 |        105 |      31 | t   -->(I am assuming 0/152D830 is
    local page_lsn corresponding to value-=105)
    
    Now I assume that *only* after doing next_wal for 31 times,  page_lsn
    shall change. But I observe strange behaviour
    
    After running nextval on sub for 7 times:
    postgres=# select * from pg_sequence_state('myseq0');
     page_lsn  | last_value | log_cnt | is_called
    -----------+------------+---------+-----------
     0/152D830 |        140 |      24 | t   -->correct
    
    After running nextval on sub for 15 more times:
    postgres=# select * from pg_sequence_state('myseq0');
     page_lsn  | last_value | log_cnt | is_called
    -----------+------------+---------+-----------
     0/152D830 |        215 |       9 | t -->correct
    (1 row)
    
    Now after running it 6 more times:
    postgres=# select * from pg_sequence_state('myseq0');
     page_lsn  | last_value | log_cnt | is_called
    -----------+------------+---------+-----------
     0/152D990 |        245 |      28 | t --> how??
    
    last_value increased in the expected way (6*5), but page_lsn changed
    and log_cnt changed before we could complete the remaining runs as
    well. Not sure why??
    
    Now if I do refresh again:
    
    postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    ALTER SUBSCRIPTION
    
    postgres=# select * from pg_subscription_rel;
     srsubid | srrelid | srsubstate | srsublsn
    ---------+---------+------------+-----------
       16385 |   16384 | r          | 0/152F380-->pub's page_lsn, same as old one.
    
    postgres=# select * from pg_sequence_state('myseq0');
     page_lsn  | last_value | log_cnt | is_called
    -----------+------------+---------+-----------
     0/152DDB8 |        105 |      31 | t
    (1 row)
    
    Now, what is this page_lsn = 0/152DDB8? Should it be the one
    corresponding to last_value=105 and thus shouldn't it match the
    previous value of  0/152D830?
    
    thanks
    Shveta
    
    
    
    
  167. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-09-29T07:04:44Z

    On Thu, 26 Sept 2024 at 11:07, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Fri, Sep 20, 2024 at 9:36 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Wed, 21 Aug 2024 at 11:54, vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Wed, 21 Aug 2024 at 08:33, Peter Smith <smithpb2250@gmail.com> wrote:
    > > > >
    > > > > Hi Vignesh, Here are my only review comments for the latest patch set.
    > > >
    > > > Thanks, these issues have been addressed in the updated version.
    > > > Additionally, I have fixed the pgindent problems that were reported
    > > > and included another advantage of this design in the file header of
    > > > the sequencesync file.
    > >
    > > The patch was not applied on top of head, here is a rebased version of
    > > the patches.
    > > I have also removed an invalidation which was  not required for
    > > sequences and a typo.
    > >
    >
    > Thank You for the patches. I would like to understand srsublsn and
    > page_lsn more. Please see the scenario below:
    >
    > I have a sequence:
    > CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    >
    > After refresh on sub:
    > postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > ALTER SUBSCRIPTION
    >
    > postgres=# select * from pg_subscription_rel;
    >  srsubid | srrelid | srsubstate | srsublsn
    > ---------+---------+------------+-----------
    >    16385 |   16384 | r          | 0/152F380 -->pub's page_lsn
    >
    >
    > postgres=# select * from pg_sequence_state('myseq0');
    >  page_lsn  | last_value | log_cnt | is_called
    > -----------+------------+---------+-----------
    >  0/152D830 |        105 |      31 | t   -->(I am assuming 0/152D830 is
    > local page_lsn corresponding to value-=105)
    >
    > Now I assume that *only* after doing next_wal for 31 times,  page_lsn
    > shall change. But I observe strange behaviour
    >
    > After running nextval on sub for 7 times:
    > postgres=# select * from pg_sequence_state('myseq0');
    >  page_lsn  | last_value | log_cnt | is_called
    > -----------+------------+---------+-----------
    >  0/152D830 |        140 |      24 | t   -->correct
    >
    > After running nextval on sub for 15 more times:
    > postgres=# select * from pg_sequence_state('myseq0');
    >  page_lsn  | last_value | log_cnt | is_called
    > -----------+------------+---------+-----------
    >  0/152D830 |        215 |       9 | t -->correct
    > (1 row)
    >
    > Now after running it 6 more times:
    > postgres=# select * from pg_sequence_state('myseq0');
    >  page_lsn  | last_value | log_cnt | is_called
    > -----------+------------+---------+-----------
    >  0/152D990 |        245 |      28 | t --> how??
    >
    > last_value increased in the expected way (6*5), but page_lsn changed
    > and log_cnt changed before we could complete the remaining runs as
    > well. Not sure why??
    
    This can occur if a checkpoint happened at that time. The regression
    test also has specific handling for this, as noted in a comment within
    the sequence.sql test file:
    -- log_cnt can be higher if there is a checkpoint just at the right
    -- time
    
    > Now if I do refresh again:
    >
    > postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > ALTER SUBSCRIPTION
    >
    > postgres=# select * from pg_subscription_rel;
    >  srsubid | srrelid | srsubstate | srsublsn
    > ---------+---------+------------+-----------
    >    16385 |   16384 | r          | 0/152F380-->pub's page_lsn, same as old one.
    >
    > postgres=# select * from pg_sequence_state('myseq0');
    >  page_lsn  | last_value | log_cnt | is_called
    > -----------+------------+---------+-----------
    >  0/152DDB8 |        105 |      31 | t
    > (1 row)
    >
    > Now, what is this page_lsn = 0/152DDB8? Should it be the one
    > corresponding to last_value=105 and thus shouldn't it match the
    > previous value of  0/152D830?
    
    After executing REFRESH PUBLICATION SEQUENCES, the publication value
    will be resynchronized, and a new LSN will be generated and updated
    for the publisher sequence (using the old value). Therefore, this is
    not a concern.
    
    Regards,
    Vignesh
    
    
    
    
  168. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2024-10-04T10:09:44Z

    On Sun, Sep 29, 2024 at 12:34 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 26 Sept 2024 at 11:07, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Fri, Sep 20, 2024 at 9:36 AM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Wed, 21 Aug 2024 at 11:54, vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > On Wed, 21 Aug 2024 at 08:33, Peter Smith <smithpb2250@gmail.com> wrote:
    > > > > >
    > > > > > Hi Vignesh, Here are my only review comments for the latest patch set.
    > > > >
    > > > > Thanks, these issues have been addressed in the updated version.
    > > > > Additionally, I have fixed the pgindent problems that were reported
    > > > > and included another advantage of this design in the file header of
    > > > > the sequencesync file.
    > > >
    > > > The patch was not applied on top of head, here is a rebased version of
    > > > the patches.
    > > > I have also removed an invalidation which was  not required for
    > > > sequences and a typo.
    > > >
    > >
    > > Thank You for the patches. I would like to understand srsublsn and
    > > page_lsn more. Please see the scenario below:
    > >
    > > I have a sequence:
    > > CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    > >
    > > After refresh on sub:
    > > postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > > ALTER SUBSCRIPTION
    > >
    > > postgres=# select * from pg_subscription_rel;
    > >  srsubid | srrelid | srsubstate | srsublsn
    > > ---------+---------+------------+-----------
    > >    16385 |   16384 | r          | 0/152F380 -->pub's page_lsn
    > >
    > >
    > > postgres=# select * from pg_sequence_state('myseq0');
    > >  page_lsn  | last_value | log_cnt | is_called
    > > -----------+------------+---------+-----------
    > >  0/152D830 |        105 |      31 | t   -->(I am assuming 0/152D830 is
    > > local page_lsn corresponding to value-=105)
    > >
    > > Now I assume that *only* after doing next_wal for 31 times,  page_lsn
    > > shall change. But I observe strange behaviour
    > >
    > > After running nextval on sub for 7 times:
    > > postgres=# select * from pg_sequence_state('myseq0');
    > >  page_lsn  | last_value | log_cnt | is_called
    > > -----------+------------+---------+-----------
    > >  0/152D830 |        140 |      24 | t   -->correct
    > >
    > > After running nextval on sub for 15 more times:
    > > postgres=# select * from pg_sequence_state('myseq0');
    > >  page_lsn  | last_value | log_cnt | is_called
    > > -----------+------------+---------+-----------
    > >  0/152D830 |        215 |       9 | t -->correct
    > > (1 row)
    > >
    > > Now after running it 6 more times:
    > > postgres=# select * from pg_sequence_state('myseq0');
    > >  page_lsn  | last_value | log_cnt | is_called
    > > -----------+------------+---------+-----------
    > >  0/152D990 |        245 |      28 | t --> how??
    > >
    > > last_value increased in the expected way (6*5), but page_lsn changed
    > > and log_cnt changed before we could complete the remaining runs as
    > > well. Not sure why??
    >
    > This can occur if a checkpoint happened at that time. The regression
    > test also has specific handling for this, as noted in a comment within
    > the sequence.sql test file:
    > -- log_cnt can be higher if there is a checkpoint just at the right
    > -- time
    
    Okay. I see. I tried by executing 'checkpoint' and can see the same behaviour.
    
    >
    > > Now if I do refresh again:
    > >
    > > postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > > ALTER SUBSCRIPTION
    > >
    > > postgres=# select * from pg_subscription_rel;
    > >  srsubid | srrelid | srsubstate | srsublsn
    > > ---------+---------+------------+-----------
    > >    16385 |   16384 | r          | 0/152F380-->pub's page_lsn, same as old one.
    > >
    > > postgres=# select * from pg_sequence_state('myseq0');
    > >  page_lsn  | last_value | log_cnt | is_called
    > > -----------+------------+---------+-----------
    > >  0/152DDB8 |        105 |      31 | t
    > > (1 row)
    > >
    > > Now, what is this page_lsn = 0/152DDB8? Should it be the one
    > > corresponding to last_value=105 and thus shouldn't it match the
    > > previous value of  0/152D830?
    >
    > After executing REFRESH PUBLICATION SEQUENCES, the publication value
    > will be resynchronized, and a new LSN will be generated and updated
    > for the publisher sequence (using the old value). Therefore, this is
    > not a concern.
    >
    
    Okay.
    
    Few comments:
    
    1)
    +static List *
    +fetch_sequence_list(WalReceiverConn *wrconn, char *subname, List *publications)
    
    --fetch_sequence_list() is not using the argument subanme anywhere.
    
    2)
    
    + if (resync_all_sequences)
    + {
    + ereport(DEBUG1,
    + errmsg_internal("sequence \"%s.%s\" of subscription \"%s\" set to INIT state",
    + get_namespace_name(get_rel_namespace(relid)),
    + get_rel_name(relid),
    + sub->name));
    + UpdateSubscriptionRelState(sub->oid, relid, SUBREL_STATE_INIT,
    +    InvalidXLogRecPtr);
    + }
    
    --Shall we have DEBUG1 after we are done with
    UpdateSubscriptionRelState? Otherwise we may end up putting this log
    statement, even if the update fails for some reason.
    
    3)
    fetch_remote_sequence_data():
    
    Should we have a macro REMOTE_SEQ_COL_COUNT 10 and use it instead of
    direct 10. Also instead of  having 1,2,3 etc in slot_getattr, we can
    have ++col and at the end we can have:
    Assert(col == REMOTE_SEQ_COL_COUNT);
    
    thanks
    Shveta
    
    
    
    
  169. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-10-08T09:45:36Z

    On Fri, 4 Oct 2024 at 15:39, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Sun, Sep 29, 2024 at 12:34 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Thu, 26 Sept 2024 at 11:07, shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > > > On Fri, Sep 20, 2024 at 9:36 AM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > On Wed, 21 Aug 2024 at 11:54, vignesh C <vignesh21@gmail.com> wrote:
    > > > > >
    > > > > > On Wed, 21 Aug 2024 at 08:33, Peter Smith <smithpb2250@gmail.com> wrote:
    > > > > > >
    > > > > > > Hi Vignesh, Here are my only review comments for the latest patch set.
    > > > > >
    > > > > > Thanks, these issues have been addressed in the updated version.
    > > > > > Additionally, I have fixed the pgindent problems that were reported
    > > > > > and included another advantage of this design in the file header of
    > > > > > the sequencesync file.
    > > > >
    > > > > The patch was not applied on top of head, here is a rebased version of
    > > > > the patches.
    > > > > I have also removed an invalidation which was  not required for
    > > > > sequences and a typo.
    > > > >
    > > >
    > > > Thank You for the patches. I would like to understand srsublsn and
    > > > page_lsn more. Please see the scenario below:
    > > >
    > > > I have a sequence:
    > > > CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    > > >
    > > > After refresh on sub:
    > > > postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > > > ALTER SUBSCRIPTION
    > > >
    > > > postgres=# select * from pg_subscription_rel;
    > > >  srsubid | srrelid | srsubstate | srsublsn
    > > > ---------+---------+------------+-----------
    > > >    16385 |   16384 | r          | 0/152F380 -->pub's page_lsn
    > > >
    > > >
    > > > postgres=# select * from pg_sequence_state('myseq0');
    > > >  page_lsn  | last_value | log_cnt | is_called
    > > > -----------+------------+---------+-----------
    > > >  0/152D830 |        105 |      31 | t   -->(I am assuming 0/152D830 is
    > > > local page_lsn corresponding to value-=105)
    > > >
    > > > Now I assume that *only* after doing next_wal for 31 times,  page_lsn
    > > > shall change. But I observe strange behaviour
    > > >
    > > > After running nextval on sub for 7 times:
    > > > postgres=# select * from pg_sequence_state('myseq0');
    > > >  page_lsn  | last_value | log_cnt | is_called
    > > > -----------+------------+---------+-----------
    > > >  0/152D830 |        140 |      24 | t   -->correct
    > > >
    > > > After running nextval on sub for 15 more times:
    > > > postgres=# select * from pg_sequence_state('myseq0');
    > > >  page_lsn  | last_value | log_cnt | is_called
    > > > -----------+------------+---------+-----------
    > > >  0/152D830 |        215 |       9 | t -->correct
    > > > (1 row)
    > > >
    > > > Now after running it 6 more times:
    > > > postgres=# select * from pg_sequence_state('myseq0');
    > > >  page_lsn  | last_value | log_cnt | is_called
    > > > -----------+------------+---------+-----------
    > > >  0/152D990 |        245 |      28 | t --> how??
    > > >
    > > > last_value increased in the expected way (6*5), but page_lsn changed
    > > > and log_cnt changed before we could complete the remaining runs as
    > > > well. Not sure why??
    > >
    > > This can occur if a checkpoint happened at that time. The regression
    > > test also has specific handling for this, as noted in a comment within
    > > the sequence.sql test file:
    > > -- log_cnt can be higher if there is a checkpoint just at the right
    > > -- time
    >
    > Okay. I see. I tried by executing 'checkpoint' and can see the same behaviour.
    >
    > >
    > > > Now if I do refresh again:
    > > >
    > > > postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > > > ALTER SUBSCRIPTION
    > > >
    > > > postgres=# select * from pg_subscription_rel;
    > > >  srsubid | srrelid | srsubstate | srsublsn
    > > > ---------+---------+------------+-----------
    > > >    16385 |   16384 | r          | 0/152F380-->pub's page_lsn, same as old one.
    > > >
    > > > postgres=# select * from pg_sequence_state('myseq0');
    > > >  page_lsn  | last_value | log_cnt | is_called
    > > > -----------+------------+---------+-----------
    > > >  0/152DDB8 |        105 |      31 | t
    > > > (1 row)
    > > >
    > > > Now, what is this page_lsn = 0/152DDB8? Should it be the one
    > > > corresponding to last_value=105 and thus shouldn't it match the
    > > > previous value of  0/152D830?
    > >
    > > After executing REFRESH PUBLICATION SEQUENCES, the publication value
    > > will be resynchronized, and a new LSN will be generated and updated
    > > for the publisher sequence (using the old value). Therefore, this is
    > > not a concern.
    > >
    >
    > Okay.
    >
    > Few comments:
    >
    > 1)
    > +static List *
    > +fetch_sequence_list(WalReceiverConn *wrconn, char *subname, List *publications)
    >
    > --fetch_sequence_list() is not using the argument subanme anywhere.
    >
    > 2)
    >
    > + if (resync_all_sequences)
    > + {
    > + ereport(DEBUG1,
    > + errmsg_internal("sequence \"%s.%s\" of subscription \"%s\" set to INIT state",
    > + get_namespace_name(get_rel_namespace(relid)),
    > + get_rel_name(relid),
    > + sub->name));
    > + UpdateSubscriptionRelState(sub->oid, relid, SUBREL_STATE_INIT,
    > +    InvalidXLogRecPtr);
    > + }
    >
    > --Shall we have DEBUG1 after we are done with
    > UpdateSubscriptionRelState? Otherwise we may end up putting this log
    > statement, even if the update fails for some reason.
    >
    > 3)
    > fetch_remote_sequence_data():
    >
    > Should we have a macro REMOTE_SEQ_COL_COUNT 10 and use it instead of
    > direct 10. Also instead of  having 1,2,3 etc in slot_getattr, we can
    > have ++col and at the end we can have:
    > Assert(col == REMOTE_SEQ_COL_COUNT);
    
    Thanks for the comments, these are addressed in the attached patch.
    
    Regards,
    Vignesh
    
  170. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2024-10-23T22:54:01Z

    On Tue, Oct 8, 2024 at 2:46 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 4 Oct 2024 at 15:39, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Sun, Sep 29, 2024 at 12:34 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Thu, 26 Sept 2024 at 11:07, shveta malik <shveta.malik@gmail.com> wrote:
    > > > >
    > > > > On Fri, Sep 20, 2024 at 9:36 AM vignesh C <vignesh21@gmail.com> wrote:
    > > > > >
    > > > > > On Wed, 21 Aug 2024 at 11:54, vignesh C <vignesh21@gmail.com> wrote:
    > > > > > >
    > > > > > > On Wed, 21 Aug 2024 at 08:33, Peter Smith <smithpb2250@gmail.com> wrote:
    > > > > > > >
    > > > > > > > Hi Vignesh, Here are my only review comments for the latest patch set.
    > > > > > >
    > > > > > > Thanks, these issues have been addressed in the updated version.
    > > > > > > Additionally, I have fixed the pgindent problems that were reported
    > > > > > > and included another advantage of this design in the file header of
    > > > > > > the sequencesync file.
    > > > > >
    > > > > > The patch was not applied on top of head, here is a rebased version of
    > > > > > the patches.
    > > > > > I have also removed an invalidation which was  not required for
    > > > > > sequences and a typo.
    > > > > >
    > > > >
    > > > > Thank You for the patches. I would like to understand srsublsn and
    > > > > page_lsn more. Please see the scenario below:
    > > > >
    > > > > I have a sequence:
    > > > > CREATE SEQUENCE myseq0 INCREMENT 5 START 100;
    > > > >
    > > > > After refresh on sub:
    > > > > postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > > > > ALTER SUBSCRIPTION
    > > > >
    > > > > postgres=# select * from pg_subscription_rel;
    > > > >  srsubid | srrelid | srsubstate | srsublsn
    > > > > ---------+---------+------------+-----------
    > > > >    16385 |   16384 | r          | 0/152F380 -->pub's page_lsn
    > > > >
    > > > >
    > > > > postgres=# select * from pg_sequence_state('myseq0');
    > > > >  page_lsn  | last_value | log_cnt | is_called
    > > > > -----------+------------+---------+-----------
    > > > >  0/152D830 |        105 |      31 | t   -->(I am assuming 0/152D830 is
    > > > > local page_lsn corresponding to value-=105)
    > > > >
    > > > > Now I assume that *only* after doing next_wal for 31 times,  page_lsn
    > > > > shall change. But I observe strange behaviour
    > > > >
    > > > > After running nextval on sub for 7 times:
    > > > > postgres=# select * from pg_sequence_state('myseq0');
    > > > >  page_lsn  | last_value | log_cnt | is_called
    > > > > -----------+------------+---------+-----------
    > > > >  0/152D830 |        140 |      24 | t   -->correct
    > > > >
    > > > > After running nextval on sub for 15 more times:
    > > > > postgres=# select * from pg_sequence_state('myseq0');
    > > > >  page_lsn  | last_value | log_cnt | is_called
    > > > > -----------+------------+---------+-----------
    > > > >  0/152D830 |        215 |       9 | t -->correct
    > > > > (1 row)
    > > > >
    > > > > Now after running it 6 more times:
    > > > > postgres=# select * from pg_sequence_state('myseq0');
    > > > >  page_lsn  | last_value | log_cnt | is_called
    > > > > -----------+------------+---------+-----------
    > > > >  0/152D990 |        245 |      28 | t --> how??
    > > > >
    > > > > last_value increased in the expected way (6*5), but page_lsn changed
    > > > > and log_cnt changed before we could complete the remaining runs as
    > > > > well. Not sure why??
    > > >
    > > > This can occur if a checkpoint happened at that time. The regression
    > > > test also has specific handling for this, as noted in a comment within
    > > > the sequence.sql test file:
    > > > -- log_cnt can be higher if there is a checkpoint just at the right
    > > > -- time
    > >
    > > Okay. I see. I tried by executing 'checkpoint' and can see the same behaviour.
    > >
    > > >
    > > > > Now if I do refresh again:
    > > > >
    > > > > postgres=# ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > > > > ALTER SUBSCRIPTION
    > > > >
    > > > > postgres=# select * from pg_subscription_rel;
    > > > >  srsubid | srrelid | srsubstate | srsublsn
    > > > > ---------+---------+------------+-----------
    > > > >    16385 |   16384 | r          | 0/152F380-->pub's page_lsn, same as old one.
    > > > >
    > > > > postgres=# select * from pg_sequence_state('myseq0');
    > > > >  page_lsn  | last_value | log_cnt | is_called
    > > > > -----------+------------+---------+-----------
    > > > >  0/152DDB8 |        105 |      31 | t
    > > > > (1 row)
    > > > >
    > > > > Now, what is this page_lsn = 0/152DDB8? Should it be the one
    > > > > corresponding to last_value=105 and thus shouldn't it match the
    > > > > previous value of  0/152D830?
    > > >
    > > > After executing REFRESH PUBLICATION SEQUENCES, the publication value
    > > > will be resynchronized, and a new LSN will be generated and updated
    > > > for the publisher sequence (using the old value). Therefore, this is
    > > > not a concern.
    > > >
    > >
    > > Okay.
    > >
    > > Few comments:
    > >
    > > 1)
    > > +static List *
    > > +fetch_sequence_list(WalReceiverConn *wrconn, char *subname, List *publications)
    > >
    > > --fetch_sequence_list() is not using the argument subanme anywhere.
    > >
    > > 2)
    > >
    > > + if (resync_all_sequences)
    > > + {
    > > + ereport(DEBUG1,
    > > + errmsg_internal("sequence \"%s.%s\" of subscription \"%s\" set to INIT state",
    > > + get_namespace_name(get_rel_namespace(relid)),
    > > + get_rel_name(relid),
    > > + sub->name));
    > > + UpdateSubscriptionRelState(sub->oid, relid, SUBREL_STATE_INIT,
    > > +    InvalidXLogRecPtr);
    > > + }
    > >
    > > --Shall we have DEBUG1 after we are done with
    > > UpdateSubscriptionRelState? Otherwise we may end up putting this log
    > > statement, even if the update fails for some reason.
    > >
    > > 3)
    > > fetch_remote_sequence_data():
    > >
    > > Should we have a macro REMOTE_SEQ_COL_COUNT 10 and use it instead of
    > > direct 10. Also instead of  having 1,2,3 etc in slot_getattr, we can
    > > have ++col and at the end we can have:
    > > Assert(col == REMOTE_SEQ_COL_COUNT);
    >
    > Thanks for the comments, these are addressed in the attached patch.
    >
    
    Here are comments on the 0001 and 0002 patches:
    
    0001 patch:
    
    read_seq_tuple() reads a buffer and acquires a lock on it, and the
    buffer is returned to the caller while being locked. So I think it's
    possible for the caller to get the page LSN even without changes.
    Since pg_sequence_state() is the sole caller that requests lsn_ret to
    be set, I think the changes of read_seq_tuples() is not necessarily
    necessary.
    
    0002 patch:
    +        Assert(all_tables && *all_tables == false);
    +        Assert(all_sequences && *all_sequences == false);
    
    I think it's better to set both *all_tables and *all_sequence to false
    at the beginning of the function to ensure this function works as
    expected regardless of their initial values.
    
    ---
            appendPQExpBufferStr(query,
                                 "SELECT p.tableoid, p.oid, p.pubname, "
                                 "p.pubowner, "
    -                            "p.puballtables, p.pubinsert,
    p.pubupdate, p.pubdelete, p.pubtruncate, p.pubviaroot "
    +                            "p.puballtables, false as
    p.puballsequences, p.pubinsert, p.pubupdate, p.pubdelete,
    p.pubtruncate, p.pubviaroot "
                                 "FROM pg_publication p");
        else if (fout->remoteVersion >= 110000)
            appendPQExpBufferStr(query,
                                 "SELECT p.tableoid, p.oid, p.pubname, "
                                 "p.pubowner, "
    -                            "p.puballtables, p.pubinsert,
    p.pubupdate, p.pubdelete, p.pubtruncate, false AS pubviaroot "
    +                            "p.puballtables, false as
    p.puballsequences, p.pubinsert, p.pubupdate, p.pubdelete,
    p.pubtruncate, false AS pubviaroot "
                                 "FROM pg_publication p");
        else
            appendPQExpBufferStr(query,
                                 "SELECT p.tableoid, p.oid, p.pubname, "
                                 "p.pubowner, "
    -                            "p.puballtables, p.pubinsert,
    p.pubupdate, p.pubdelete, false AS pubtruncate, false AS pubviaroot "
    +                            "p.puballtables, false as
    p.puballsequences, p.pubinsert, p.pubupdate, p.pubdelete, false AS
    pubtruncate, false AS pubviaroot "
                                 "FROM pg_publication p");
    
    The column name should be puballsequences, not p.puballsequences.
    
    ---
    IIUC the changes of describeOneTableDetails() includes two kinds of
    changes: refactoring to use printTable() instead of printQuery(), and
    adding publications that includes the sequence. Is the first
    refactoring necessary for the second change? If not, should it be done
    in a separate patch?
    fg
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  171. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-10-31T09:27:35Z

    On Thu, 24 Oct 2024 at 04:24, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > Here are comments on the 0001 and 0002 patches:
    >
    > 0001 patch:
    >
    > read_seq_tuple() reads a buffer and acquires a lock on it, and the
    > buffer is returned to the caller while being locked. So I think it's
    > possible for the caller to get the page LSN even without changes.
    > Since pg_sequence_state() is the sole caller that requests lsn_ret to
    > be set, I think the changes of read_seq_tuples() is not necessarily
    > necessary.
    
    Modified
    
    > 0002 patch:
    > +        Assert(all_tables && *all_tables == false);
    > +        Assert(all_sequences && *all_sequences == false);
    >
    > I think it's better to set both *all_tables and *all_sequence to false
    > at the beginning of the function to ensure this function works as
    > expected regardless of their initial values.
    
    Modified
    
    > ---
    >         appendPQExpBufferStr(query,
    >                              "SELECT p.tableoid, p.oid, p.pubname, "
    >                              "p.pubowner, "
    > -                            "p.puballtables, p.pubinsert,
    > p.pubupdate, p.pubdelete, p.pubtruncate, p.pubviaroot "
    > +                            "p.puballtables, false as
    > p.puballsequences, p.pubinsert, p.pubupdate, p.pubdelete,
    > p.pubtruncate, p.pubviaroot "
    >                              "FROM pg_publication p");
    >     else if (fout->remoteVersion >= 110000)
    >         appendPQExpBufferStr(query,
    >                              "SELECT p.tableoid, p.oid, p.pubname, "
    >                              "p.pubowner, "
    > -                            "p.puballtables, p.pubinsert,
    > p.pubupdate, p.pubdelete, p.pubtruncate, false AS pubviaroot "
    > +                            "p.puballtables, false as
    > p.puballsequences, p.pubinsert, p.pubupdate, p.pubdelete,
    > p.pubtruncate, false AS pubviaroot "
    >                              "FROM pg_publication p");
    >     else
    >         appendPQExpBufferStr(query,
    >                              "SELECT p.tableoid, p.oid, p.pubname, "
    >                              "p.pubowner, "
    > -                            "p.puballtables, p.pubinsert,
    > p.pubupdate, p.pubdelete, false AS pubtruncate, false AS pubviaroot "
    > +                            "p.puballtables, false as
    > p.puballsequences, p.pubinsert, p.pubupdate, p.pubdelete, false AS
    > pubtruncate, false AS pubviaroot "
    >                              "FROM pg_publication p");
    >
    > The column name should be puballsequences, not p.puballsequences.
    
    Modified
    
    > ---
    > IIUC the changes of describeOneTableDetails() includes two kinds of
    > changes: refactoring to use printTable() instead of printQuery(), and
    > adding publications that includes the sequence. Is the first
    > refactoring necessary for the second change? If not, should it be done
    > in a separate patch?
    
    We are adding publication titles as footers to the sequence
    description, each with different publication names. Since the number
    of publications is unknown in advance, we will first determine the
    total number of publications, then allocate the necessary size for the
    footers. We will append footers[0] with either 'Owned by' or 'Sequence
    for identity column,' followed by the publication titles.
    Additionally, these will be subject to version checks. In this case,
    using printTable instead of printQuery is preferable, as it simplifies
    the code.
    
    The attached patch has the changes for the fixes.
    
    Regards,
    Vignesh
    
  172. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-11-18T10:19:33Z

    On Thu, 31 Oct 2024 at 14:57, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 24 Oct 2024 at 04:24, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > Here are comments on the 0001 and 0002 patches:
    > >
    > > 0001 patch:
    > >
    > > read_seq_tuple() reads a buffer and acquires a lock on it, and the
    > > buffer is returned to the caller while being locked. So I think it's
    > > possible for the caller to get the page LSN even without changes.
    > > Since pg_sequence_state() is the sole caller that requests lsn_ret to
    > > be set, I think the changes of read_seq_tuples() is not necessarily
    > > necessary.
    >
    > Modified
    >
    > > 0002 patch:
    > > +        Assert(all_tables && *all_tables == false);
    > > +        Assert(all_sequences && *all_sequences == false);
    > >
    > > I think it's better to set both *all_tables and *all_sequence to false
    > > at the beginning of the function to ensure this function works as
    > > expected regardless of their initial values.
    >
    > Modified
    >
    > > ---
    > >         appendPQExpBufferStr(query,
    > >                              "SELECT p.tableoid, p.oid, p.pubname, "
    > >                              "p.pubowner, "
    > > -                            "p.puballtables, p.pubinsert,
    > > p.pubupdate, p.pubdelete, p.pubtruncate, p.pubviaroot "
    > > +                            "p.puballtables, false as
    > > p.puballsequences, p.pubinsert, p.pubupdate, p.pubdelete,
    > > p.pubtruncate, p.pubviaroot "
    > >                              "FROM pg_publication p");
    > >     else if (fout->remoteVersion >= 110000)
    > >         appendPQExpBufferStr(query,
    > >                              "SELECT p.tableoid, p.oid, p.pubname, "
    > >                              "p.pubowner, "
    > > -                            "p.puballtables, p.pubinsert,
    > > p.pubupdate, p.pubdelete, p.pubtruncate, false AS pubviaroot "
    > > +                            "p.puballtables, false as
    > > p.puballsequences, p.pubinsert, p.pubupdate, p.pubdelete,
    > > p.pubtruncate, false AS pubviaroot "
    > >                              "FROM pg_publication p");
    > >     else
    > >         appendPQExpBufferStr(query,
    > >                              "SELECT p.tableoid, p.oid, p.pubname, "
    > >                              "p.pubowner, "
    > > -                            "p.puballtables, p.pubinsert,
    > > p.pubupdate, p.pubdelete, false AS pubtruncate, false AS pubviaroot "
    > > +                            "p.puballtables, false as
    > > p.puballsequences, p.pubinsert, p.pubupdate, p.pubdelete, false AS
    > > pubtruncate, false AS pubviaroot "
    > >                              "FROM pg_publication p");
    > >
    > > The column name should be puballsequences, not p.puballsequences.
    >
    > Modified
    >
    > > ---
    > > IIUC the changes of describeOneTableDetails() includes two kinds of
    > > changes: refactoring to use printTable() instead of printQuery(), and
    > > adding publications that includes the sequence. Is the first
    > > refactoring necessary for the second change? If not, should it be done
    > > in a separate patch?
    >
    > We are adding publication titles as footers to the sequence
    > description, each with different publication names. Since the number
    > of publications is unknown in advance, we will first determine the
    > total number of publications, then allocate the necessary size for the
    > footers. We will append footers[0] with either 'Owned by' or 'Sequence
    > for identity column,' followed by the publication titles.
    > Additionally, these will be subject to version checks. In this case,
    > using printTable instead of printQuery is preferable, as it simplifies
    > the code.
    >
    > The attached patch has the changes for the fixes.
    
    The patch needed to be rebased; here is the updated version.
    
    Regards,
    Vignesh
    
  173. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-12-08T14:27:08Z

    On Mon, 18 Nov 2024 at 10:19, vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > The patch needed to be rebased; here is the updated version.
    
    The patch needed to be rebased; here is the updated version.
    
    Regards,
    Vignesh
    
  174. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-12-11T10:12:36Z

    On Sun, 8 Dec 2024 at 19:57, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 18 Nov 2024 at 10:19, vignesh C <vignesh21@gmail.com> wrote:
    >
    > The patch needed to be rebased; here is the updated version.
    
    The patch needed to be rebased; here is the updated version.
    
    Regards,
    Vignesh
    
  175. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-12-18T02:41:57Z

    Hi Vignesh.
    
    Here are some review comments for patch v20241211-0001.
    
    ======
    src/backend/commands/sequence.c
    
    pg_sequence_state:
    
    
    1.
    + TupleDesc tupdesc;
    + HeapTuple tuple;
    + Datum values[4];
    + bool nulls[4] = {false, false, false, false};
    
    SUGGESTION
    bool nulls[4] = {0};
    
    The above achieves the same thing, but more succinctly, and I think it
    is a common enough pattern in the PG source code.
    
    ~~~
    
    2.
    + seq = read_seq_tuple(seqrel, &buf, &seqtuple);
    + page = BufferGetPage(buf);
    + lsn = PageGetLSN(page);
    +
    + last_value = seq->last_value;
    + log_cnt = seq->log_cnt;
    + is_called = seq->is_called;
    
    Move the blank line, so the 'lsn' assignment will be grouped with the
    other 3 assignments which are part of the return tuple.
    
    ~~~
    
    3.
    + /* How many fetches remain before a new WAL record has to be written */
    + values[2] = Int64GetDatum(log_cnt);
    
    Trivial change to use the same wording as the documentation.
    
    /has to/must/
    
    ======
    
    (The attached NITPICKS patch includes the above suggestions)
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
  176. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-12-18T06:09:48Z

    Hi Vignesh,
    
    Here are some review comments for the patch v20241211-0002.
    
    ======
    doc/src/sgml/ref/create_publication.sgml
    
    1.
    +<phrase>where <replaceable class="parameter">object
    type</replaceable> is one of:</phrase>
    +
    +    TABLES
    +    SEQUENCES
    
    The replaceable "object_type" is missing an underscore.
    
    ~~~
    
    publish option effect fro SEQUENCE replication?
    
    2.
    It's not obvious to me if the SEQUENCE replication stuff is affected
    but the setting of pubactions (ie the 'publish' option). I'm thinking
    that probably anything to do with SEQUENCEs may no be considered a DML
    operation, but if that is true it might be better to explicitly say
    so.
    
    Also, we might need to include a test to show even if publish='' that
    the SEQUENCE synchronization is not affected.
    
    
    ======
    src/backend/commands/publicationcmds.c
    
    CreatePublication:
    
    3.
    - /* FOR ALL TABLES requires superuser */
    - if (stmt->for_all_tables && !superuser())
    + /* FOR ALL TABLES or FOR ALL SEQUENCES requires superuser */
    + if ((stmt->for_all_tables || stmt->for_all_sequences) && !superuser())
      ereport(ERROR,
      (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    - errmsg("must be superuser to create FOR ALL TABLES publication")));
    + errmsg("must be superuser to create a %s publication",
    + stmt->for_all_tables ? "FOR ALL TABLES" :
    + "FOR ALL SEQUENCES")));
    
    It seems a quirk that if FOR ALL TABLES and FOR ALL SEQUENCES are
    specified at the same time then you would only get the "FOR ALL
    TABLES" error, but maybe that is OK?
    
    ~~~
    
    AlterPublicationOwner_internal:
    
    4.
    Ditto quirk as commented above, but maybe it is OK.
    
    ======
    src/bin/psql/describe.c
    
    describePublications:
    
    5.
    It seems the ordering of the local variables, and then the attributes
    in the SQL, and the headings in the "describe" output are a bit
    muddled.
    
    IMO it might be better to always keep things in the same order as the
    eventual display headings. So anything to do with puballsequences
    should be immediately after anything to do with puballtables.
    
    (There are multiple changes needed in this function to rearrange
    things to be this way).
    
    ~~~
    
    6.
    The following seems wrong because now somehow there are two lots of
    index 9 (???)
    
    -----
    printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false);
    printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false);
    if (has_pubsequence)
      printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false); /*
    all sequences */
    printTableAddCell(&cont, PQgetvalue(res, i, 4), false, false);
    printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
    printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false);
    if (has_pubtruncate)
      printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
    if (has_pubgencols)
      printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
    if (has_pubviaroot)
      printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
    -----
    
    
    ======
    src/test/regress/expected/psql.out
    
    7.
    +\dRp+ regress_pub_forallsequences1
    +                                            Publication
    regress_pub_forallsequences1
    +          Owner           | All tables | All sequences | Inserts |
    Updates | Deletes | Truncates | Generated columns | Via root
    +--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
    + regress_publication_user | f          | f             | t       | t
         | t       | t         | f                 | f
    +(1 row)
    +
    
    The expected value of 'f' for "All sequences" looks wrong to me. I
    think this might be a manifestation of that duplicated '9' index
    mentioned in an earlier review comment #6.
    
    ~~~
    
    8.
    +\dRp+ regress_pub_for_allsequences_alltables
    +                                       Publication
    regress_pub_for_allsequences_alltables
    +          Owner           | All tables | All sequences | Inserts |
    Updates | Deletes | Truncates | Generated columns | Via root
    +--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
    + regress_publication_user | t          | f             | t       | t
         | t       | t         | f                 | f
    +(1 row)
    +
    
    The expected value of 'f' for "All sequences" looks wrong to me. I
    think this might be a manifestation of that duplicated '9' index
    mentioned in an earlier review comment #6.
    
    ~~~
    
    9.
     \dRp+ testpub_forparted
    -                                         Publication testpub_forparted
    -          Owner           | All tables | Inserts | Updates | Deletes
    | Truncates | Generated columns | Via root
    ---------------------------+------------+---------+---------+---------+-----------+-------------------+----------
    - regress_publication_user | f          | t       | t       | t
    | t         | f                 | t
    +                                                 Publication testpub_forparted
    +          Owner           | All tables | All sequences | Inserts |
    Updates | Deletes | Truncates | Generated columns | Via root
    +--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
    + regress_publication_user | f          | t             | t       | t
         | t       | t         | f                 | t
    
    
    AFAIK these partition tests should not be impacting the "All
    Sequences" flag value, so the expected value of 't' for "All
    sequences" looks wrong to me. I think this might be a manifestation of
    that duplicated '9' index mentioned in an earlier review comment #6.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  177. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-12-18T23:28:25Z

    Hi Vignesh,
    
    Here are some review comments for the patch v20241211-0003.
    
    ======
    src/backend/replication/logical/syncutils.c
    
    1.
    +typedef enum
    +{
    + SYNC_RELATIONS_STATE_NEEDS_REBUILD,
    + SYNC_RELATIONS_STATE_REBUILD_STARTED,
    + SYNC_RELATIONS_STATE_VALID,
    +} SyncingRelationsState;
    +
    
    Even though the patch's intent was only to "move" this from
    tablsync.c, this enum probably deserved a comment describing its
    purpose.
    
    ~~~
    
    2.
    +List    *table_states_not_ready = NIL;
    
    Maybe it is convenient to move this, but there is something about this
    list being exposed out of a "utils" module back to the tablesync.c
    module that seems a bit strange. Would it make more sense for this to
    be the other way around e.g. declared in the tablesync.c but exposed
    to the syncutils.c? (and then similarly in subsequent patch 0004 the
    sequence_states_not_ready would belong in the sequencesync.c)
    
    ~~~
    
    3.
    +/*
    + * Process possible state change(s) of tables that are being synchronized.
    + */
    +void
    +SyncProcessRelations(XLogRecPtr current_lsn)
    +{
    
    IIUC there was a deliberate effort to rename some comments and
    functions to say "relations" instead of "tables". AFAICT that was done
    to encompass the SEQUENCES which can fit under the umbrella of
    "relations". Anyway, it becomes confusing sometimes when there is a
    mismatch. For example, here is a function (relations) with a function
    comment (tables).
    
    ~~~
    
    4.
    +/*
    + * Common code to fetch the up-to-date sync state info into the static lists.
    + *
    + * Returns true if subscription has 1 or more tables, else false.
    + *
    + * Note: If this function started the transaction (indicated by the parameter)
    + * then it is the caller's responsibility to commit it.
    + */
    +bool
    +FetchRelationStates(bool *started_tx)
    
    Here is another place where the function name is "relations", but the
    function comment refers to "tables".
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  178. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-12-20T00:56:28Z

    Hi Vignesh,
    
    Here are some review comments for the patch v20241211-0004.
    
    ======
    GENERAL
    
    1.
    There are more than a dozen places where the relation (relkind) is
    checked to see if it is a SEQUENCE:
    
    e.g. + get_rel_relkind(subrel->srrelid) != RELKIND_SEQUENCE &&
    e.g. + if (get_rel_relkind(subrel->srrelid) != RELKIND_SEQUENCE)
    e.g. + if (relkind == RELKIND_SEQUENCE && !get_sequences)
    e.g. + if (relkind != RELKIND_SEQUENCE && !get_tables)
    e.g. + relkind == RELKIND_SEQUENCE ? "sequence" : "table",
    e.g. + if (relkind != RELKIND_SEQUENCE)
    e.g. + relkind == RELKIND_SEQUENCE ? "sequence" : "table",
    e.g. + if (get_rel_relkind(sub_remove_rels[off].relid) == RELKIND_SEQUENCE)
    e.g. + if (get_rel_relkind(relid) != RELKIND_SEQUENCE)
    e.g. + relkind != RELKIND_SEQUENCE)
    e.g. + Assert(get_rel_relkind(rstate->relid) == RELKIND_SEQUENCE);
    e.g. + Assert(relkind == RELKIND_SEQUENCE);
    e.g. + if (get_rel_relkind(rstate->relid) == RELKIND_SEQUENCE)
    e.g. + Assert(get_rel_relkind(rstate->relid) != RELKIND_SEQUENCE);
    
    I am wondering if the code might be improved slightly by adding one new macro:
    
    #define RELKIND_IS_SEQUENCE(relkind) ((relkind) == RELKIND_SEQUENCE)
    
    ======
    Commit message
    
    2.
    1) CREATE SUBSCRIPTION
        - (PG17 command syntax is unchanged)
        - The subscriber retrieves sequences associated with publications.
        - Publisher sequences are added to pg_subscription_rel with INIT state.
        - Initiates the sequencesync worker (see above) to synchronize all
          sequences.
    
    ~
    
    Shouldn't this say "Published sequences" instead of "Publisher sequences"?
    
    I guess if the patch currently supports only ALL SEQUENCES then maybe
    it amounts to the same thing, but IMO "Published" seems more correct.
    
    ~~~
    
    3.
    2) ALTER SUBSCRIPTION ... REFRESH PUBLICATION
        - (PG17 command syntax is unchanged)
        - Dropped publisher sequences are removed from pg_subscription_rel.
        - New publisher sequences are added to pg_subscription_rel with INIT state.
        - Initiates the sequencesync worker (see above) to synchronize only
          newly added sequences.
    
    3) ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES
        - The patch introduces this new command to refresh all sequences
        - Dropped publisher sequences are removed from pg_subscription_rel.
        - New publisher sequences are added to pg_subscription_rel
        - All sequences in pg_subscription_rel are reset to INIT state.
        - Initiates the sequencesync worker (see above) to synchronize all
          sequences.
    
    ~
    
    Ditto previous comment -- maybe those should say "Newly published
    sequences" instead of "New publisher sequences"/
    
    ~~~
    
    4.
    Should there be some mention of the WARNING logged if sequence
    parameter differences are detected?
    
    ======
    src/backend/catalog/pg_subscription.c
    
    GetSubscriptionRelations:
    
    5.
    + * all_states:
    + * If getting tables, if all_states is true get all tables, otherwise
    + * only get tables that have not reached READY state.
    + * If getting sequences, if all_states is true get all sequences,
    + * otherwise only get sequences that are in INIT state.
    + *
    + * The returned list is palloc'ed in the current memory context.
    
    and
    
    - if (not_ready)
    + if (!all_states)
      ScanKeyInit(&skey[nkeys++],
      Anum_pg_subscription_rel_srsubstate,
      BTEqualStrategyNumber, F_CHARNE,
                        CharGetDatum(SUBREL_STATE_READY));
    ~
    
    It was a bit confusing that the code for (!all_states) is excluding
    everything that is not in SUBREL_STATE_READY, but OTOH the function
    comment for sequences it said "that are in INIT state". Maybe that
    function comment for sequence also should have said "that have not
    reached READY state (i.e. are still in INIT state)" to better match
    the code.
    
    ~~~
    
    6.
    + /* Skip sequences if they were not requested */
    + if (relkind == RELKIND_SEQUENCE && !get_sequences)
    + continue;
    +
    + /* Skip tables if they were not requested */
    + if (relkind != RELKIND_SEQUENCE && !get_tables)
    + continue;
    
    Somehow, I feel this logic would seem simpler if expressed differently
    to make it more explicit that the relation is either a table or a
    sequence. e.g. by adding some variables.
    
    SUGGESTION:
    
    bool is_sequence;
    bool is_table;
    
    ...
    
    /* Relation is either a sequence or a table */
    is_sequence = get_rel_relkind(subrel->srrelid) == RELKIND_SEQUENCE;
    is_table = !is_sequence;
    
    /* Skip sequences if they were not requested */
    if (!get_sequences && is_sequence)
      continue;
    
    /* Skip tables if they were not requested */
    if (!get_tables && is_table)
      continue;
    
    ======
    src/backend/commands/sequence.c
    
    7.
     /*
    - * Implement the 2 arg setval procedure.
    - * See do_setval for discussion.
    + * Implement the 2 arg set sequence procedure.
    + * See SetSequence for discussion.
      */
     Datum
     setval_oid(PG_FUNCTION_ARGS)
    
    ~
    
    Not sure this function comment is right. Shouldn't it still say
    "Implement the 2 arg setval procedure."
    
    ~~~
    
    8.
     /*
    - * Implement the 3 arg setval procedure.
    - * See do_setval for discussion.
    + * Implement the 3 arg set sequence procedure.
    + * See SetSequence for discussion.
      */
     Datum
     setval3_oid(PG_FUNCTION_ARGS)
    
    ~
    
    Not sure this function comment is right. Shouldn't it still say
    "Implement the 3 arg setval procedure."
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    AlterSubscription_refresh:
    
    9.
    + * If 'refresh_tables' is true, update the subscription by adding or removing
    + * tables that have been added or removed since the last subscription creation
    + * or refresh publication.
    + *
    + * If 'refresh_sequences' is true, update the subscription by adding
    or removing
    + * sequences that have been added or removed since the last subscription
    + * creation or publication refresh.
    
    The first para says "refresh publication". The second para says
    "publication refresh", but I guess it should also be saying "refresh
    publication".
    
    ~~~
    
    10.
    + if (resync_all_sequences)
    + {
    +
    + UpdateSubscriptionRelState(sub->oid, relid, SUBREL_STATE_INIT,
    +    InvalidXLogRecPtr);
    + ereport(DEBUG1,
    + errmsg_internal("sequence \"%s.%s\" of subscription \"%s\" set to INIT state",
    + get_namespace_name(get_rel_namespace(relid)),
    + get_rel_name(relid),
    + sub->name));
    + }
    
    Has unnecessary blank line.
    
    ~~~
    
    AlterSubscription:
    
    11.
    Some of the generic error messages in this function are now
    potentially misleading.
    
    e.g. There are multiple places in this function that say "ALTER
    SUBSCRIPTION ... REFRESH", meaning ALTER SUBSCRIPTION <subname>
    REFRESH PUBLICATION, but not meaning ALTER SUBSCRIPTION <subname>
    REFRESH PUBLICATION SEQUENCES, so possibly those need to be modified
    to eliminate any ambiguity.
    
    (Actually, maybe it is not only in this function -- the short form
    "ALTER SUBSCRIPTION ... REFRESH" seems to be scattered in other
    comments in this file also).
    
    ~~~
    
    12.
    - logicalrep_worker_stop(w->subid, w->relid);
    + /* Worker might have exited because of an error */
    + if (w->type == WORKERTYPE_UNKNOWN)
    + continue;
    +
    + logicalrep_worker_stop(w->subid, w->relid, w->type);
    
    It may be better to put that special case WORKERTYPE_UNKNOWN condition
    as a quick exit within the logicalrep_worker_stop() function.
    
    ======
    src/backend/replication/logical/launcher.c
    
    logicalrep_worker_find:
    
    13.
    + Assert(wtype == WORKERTYPE_TABLESYNC ||
    +    wtype == WORKERTYPE_SEQUENCESYNC ||
    +    wtype == WORKERTYPE_APPLY);
    +
    
    The master version of this function checked for
    isParallelApplyWorker(w), but now if a WORKERTYPE_PARALLEL_APPLY ever
    got to here it would fail the above Assert. So, is the patch code OK,
    or do we still need to also account for a possible
    WORKERTYPE_PARALLEL_APPLY reaching here?
    
    ~~~
    
    logicalrep_worker_stop:
    
    14.
    worker = logicalrep_worker_find(subid, relid, wtype, false);
    
    if (worker)
    {
      Assert(!isParallelApplyWorker(worker));
      logicalrep_worker_stop_internal(worker, SIGTERM);
    }
    
    ~
    
    This code is not changed much from before, so it first finds the
    worker, but then asserts that it must not be not a parallel apply
    worker. But now, since the wtype is known and passed to the function
    why not move the Assert up-front based on the wtype and before even
    doing the 'find'?
    
    ======
    .../replication/logical/sequencesync.c
    
    ProcessSyncingSequencesForApply:
    
    15.
    + /*
    + * Check if there is a sequence worker already running?
    + */
    + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
    +
    + syncworker = logicalrep_worker_find(MyLogicalRepWorker->subid,
    + InvalidOid, WORKERTYPE_SEQUENCESYNC,
    + true);
    + if (syncworker)
    + {
    + /* Now safe to release the LWLock */
    + LWLockRelease(LogicalRepWorkerLock);
    + break;
    + }
    
    15a.
    Comment: /sequence worker/sequencesync worker/
    
    ~
    
    15b.
    Maybe it's better to call this variable 'sequencesync_worker' or
    similar because sync worker is too generic
    
    ~~~
    
    fetch_remote_sequence_data:
    
    16.
    +/*
    + * fetch_remote_sequence_data
    + *
    + * Retrieves sequence data (last_value, log_cnt, page_lsn, and is_called)
    + * from a remote node.
    
    The SELECT of this function fetch a lot more columns, so why are only
    these few mentioned in the function comment?
    
    ~
    
    17.
    + res = walrcv_exec(conn, cmd.data, REMOTE_SEQ_COL_COUNT, tableRow);
    + pfree(cmd.data);
    +
    + if (res->status != WALRCV_OK_TUPLES)
    + ereport(ERROR,
    + errmsg("could not receive sequence list from the publisher: %s",
    +    res->err));
    
    That error msg does seem quite right. IIUC, this is just the data from
    a single sequence; it is not a "sequence list".
    
    ~~~
    
    report_mismatched_sequences:
    
    18.
    +static void
    +report_mismatched_sequences(StringInfo mismatched_seqs)
    +{
    + if (mismatched_seqs->len)
    + {
    + ereport(WARNING,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("parameters differ for the remote and local sequences (%s)
    for subscription \"%s\"",
    +    mismatched_seqs->data, MySubscription->name),
    + errhint("Alter/Re-create local sequences to have the same parameters
    as the remote sequences."));
    +
    + resetStringInfo(mismatched_seqs);
    + }
    +}
    
    I'm confused. The errhint says "Alter/Re-create local sequences to
    have the same parameters", but in the function 'copy_sequence' there
    was the code (below) that seems to be already setting the sequence
    values (SetSequence) regardless of whether it detected
    sequence_mismatch true/false.
    
    + *sequence_mismatch = !fetch_remote_sequence_data(conn, relid, remoteid,
    + nspname, relname,
    + &seq_log_cnt, &seq_is_called,
    + &seq_page_lsn, &seq_last_value);
    +
    + SetSequence(RelationGetRelid(rel), seq_last_value, seq_is_called,
    + seq_log_cnt);
    
    Is the setting regardless like that OK, or just going to lead to weird
    integrity errors?
    
    ~~~
    
    LogicalRepSyncSequences:
    
    19.
    +/*
    + * Start syncing the sequences in the sync worker.
    + */
    +static void
    +LogicalRepSyncSequences(void)
    
    /sync worker/sequencesync worker/
    
    ~~~
    
    20.
    + curr_seq++;
    +
    + /*
    + * Have we reached the end of the current batch of sequences, or last
    + * remaining sequences to synchronize?
    + */
    + if (((curr_seq % MAX_SEQUENCES_SYNC_PER_BATCH) == 0) ||
    + curr_seq == seq_count)
    + {
    + /* LOG all the sequences synchronized during current batch. */
    + for (int i = (curr_seq - 1) - ((curr_seq - 1) % MAX_SEQUENCES_SYNC_PER_BATCH);
    + i < curr_seq; i++)
    + {
    
    The calculation is quite tricky.
    
    IMO this might all be simplified if you have another variable like
    'batch_seq' that just ranges from 0 -- MAX_SEQUENCES_SYNC_PER_BATCH,
    then do something like:
    
    SUGGESTION:
    
    cur_seq++;
    batch_seq++;
    
    if (batch_seq >= MAX_SEQUENCES_SYNC_PER_BATCH || cur_seq == seq_count)
    {
      /* Process the batch. */
    
      ...
    
      /* LOG all the sequences synchronized during the current batch. */
      for (int i = 0; i < batch_seq; i++)
      {
        ...
      }
    
      /* Prepare for next batch */
      batch_seq = 0;
    }
    
    ======
    src/backend/replication/logical/syncutils.c
    
    21.
     List    *table_states_not_ready = NIL;
    +List    *sequence_states_not_ready = NIL;
    
    I thought this declaration belonged more in the sequencesync.c file.
    
    ~~~
    
    SyncProcessRelations:
    
    22.
     /*
    - * Process possible state change(s) of tables that are being synchronized.
    + * Process possible state change(s) of tables that are being synchronized and
    + * start new tablesync workers for the newly added tables and start new
    + * sequencesync worker for the newly added sequences.
      */
    
    /added tables and start new sequencesync worker/added tables. Also,
    start a new sequencesync worker/
    
    ~~~
    
    FetchRelationStates:
    
    23.
    - * Note: If this function started the transaction (indicated by the parameter)
    - * then it is the caller's responsibility to commit it.
    + * Returns true if subscription has 1 or more tables, else false.
      */
     bool
    -FetchRelationStates(bool *started_tx)
    +FetchRelationStates(void)
    
    Partly because of the name (relations), I felt this might be better to
    be a void function and the returned value would be passed back by
    references (bool *has_tables).
    
    ======
    src/backend/replication/logical/worker.c
    
    SetupApplyOrSyncWorker:
    
    24.
    +
    + if (am_sequencesync_worker())
    + before_shmem_exit(logicalrep_seqsyncworker_failuretime, (Datum) 0);
    
    There should be a comment saying what this callback is for.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  179. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2024-12-20T02:34:45Z

    Hi Vignesh.
    
    Here are some review comments for the patch v20241211-0005.
    
    ======
    doc/src/sgml/logical-replication.sgml
    
    Section "29.6.1. Sequence Definition Mismatches"
    
    1.
    +   <warning>
    +    <para>
    +     If there are differences in sequence definitions between the publisher and
    +     subscriber, a WARNING is logged.
    +    </para>
    +   </warning>
    
    Maybe this should say *when* this happens.
    
    SUGGESTION
    During sequence synchronization, the sequence definitions of the
    publisher and the subscriber are compared. A WARNING is logged if any
    differences are detected.
    
    ~~~
    
    Section "29.6.3. Examples"
    
    2.
    Should the Examples section also have an example of ALTER SUBSCRIPTION
    ... REFRESH PUBLICATION to demonstrate (like in the TAP tests) that if
    the sequences are already known, then those are not synchronised?
    
    ~~~
    
    Section "29.8. Restrictions"
    
    3.
    +     Incremental sequence changes are not replicated.  The data in serial or
    +     identity columns backed by sequences will of course be replicated as part
    +     of the table, but the sequence itself would still show the start value on
    +     the subscriber.  If the subscriber is used as a read-only database, then
    +     this should typically not be a problem.  If, however, some kind of
    +     switchover or failover to the subscriber database is intended, then the
    +     sequences would need to be updated to the latest values, either
    by executing
    +     <link linkend="sql-altersubscription-params-refresh-publication-sequences">
    +     <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES</command></link>
    +     or by copying the current data from the publisher (perhaps using
    +     <command>pg_dump</command>) or by determining a sufficiently high value
    +     from the tables themselves.
    
    I don't know if you need to mention it, or maybe it is too obvious,
    but the suggestion here to use "ALTER SUBSCRIPTION ... REFRESH
    PUBLICATION SEQUENCES" assumed you've already arranged for the
    PUBLICATION to be publishing sequences before this.
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    4.
              <para>
    -          Specifies whether to copy pre-existing data in the publications
    -          that are being subscribed to when the replication starts.
    -          The default is <literal>true</literal>.
    +          Specifies whether to copy pre-existing data for tables and
    synchronize
    +          sequences in the publications that are being subscribed to
    when the replication
    +          starts. The default is <literal>true</literal>.
              </para>
    
    This is talking also about "synchronize sequences" when the
    replication starts, but it is a bit confusing. IIUC, the .. REFRESH
    PUBLICATION only synchronizes *newly added* sequences anyway, so does
    it mean even that will not happen if copy_data=false?
    
    I think this option needs more clarification on how it interacts with
    sequences. Also, I don't recall seeing any test for sequences and
    copy_data in the patch 0004 TAP tests, so maybe something needs to be
    added there too.
    
    ~~~
    
    5.
    +     <para>
    +      See <xref linkend="sequences-out-of-sync"/> for recommendations on how
    +      to identify sequences and handle out-of-sync sequences.
    +     </para>
    
    /on how to identify sequences and handle out-of-sync sequences./on how
    to identify and handle out-of-sync sequences./
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  180. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-12-23T07:20:14Z

    On Wed, 18 Dec 2024 at 11:40, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Here are some review comments for the patch v20241211-0002.
    > ~~~
    >
    > publish option effect fro SEQUENCE replication?
    >
    > 2.
    > It's not obvious to me if the SEQUENCE replication stuff is affected
    > but the setting of pubactions (ie the 'publish' option). I'm thinking
    > that probably anything to do with SEQUENCEs may no be considered a DML
    > operation, but if that is true it might be better to explicitly say
    > so.
    >
    > Also, we might need to include a test to show even if publish='' that
    > the SEQUENCE synchronization is not affected.
    
    Since we just synchronize the data and we don't replicate incremental
    changes and insert/update/delete are only for incremental data sync, I
    felt we need not mention this explicitly in this case as we have
    mentioned that "Incremental sequence changes are not replicated" in
    0005 patch. I also felt that there was no need to add a testcase for
    this as currently it has nothing to do with this option.
    
    >
    > ======
    > src/backend/commands/publicationcmds.c
    >
    > CreatePublication:
    >
    > 3.
    > - /* FOR ALL TABLES requires superuser */
    > - if (stmt->for_all_tables && !superuser())
    > + /* FOR ALL TABLES or FOR ALL SEQUENCES requires superuser */
    > + if ((stmt->for_all_tables || stmt->for_all_sequences) && !superuser())
    >   ereport(ERROR,
    >   (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    > - errmsg("must be superuser to create FOR ALL TABLES publication")));
    > + errmsg("must be superuser to create a %s publication",
    > + stmt->for_all_tables ? "FOR ALL TABLES" :
    > + "FOR ALL SEQUENCES")));
    >
    > It seems a quirk that if FOR ALL TABLES and FOR ALL SEQUENCES are
    > specified at the same time then you would only get the "FOR ALL
    > TABLES" error, but maybe that is OK?
    
    I have modified the error message slightly
    
    > ~~~
    >
    > AlterPublicationOwner_internal:
    >
    > 4.
    > Ditto quirk as commented above, but maybe it is OK.
    
    I have modified the error message slightly
    
    The rest of the comments are fixed. Also the comments from [1] are fixed.
    The attached v202412123 version patch has the changes for the same.
    
    [1] - https://www.postgresql.org/message-id/CAHut%2BPsk1V2eUL_nreWp1trO1iSDqhDtBnfu65PrsoorpuNzKA%40mail.gmail.com
    
    Regards,
    Vignesh
    
  181. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-12-23T07:22:28Z

    On Thu, 19 Dec 2024 at 04:58, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Here are some review comments for the patch v20241211-0003.
    >
    > ~~~
    >
    > 4.
    > +/*
    > + * Common code to fetch the up-to-date sync state info into the static lists.
    > + *
    > + * Returns true if subscription has 1 or more tables, else false.
    > + *
    > + * Note: If this function started the transaction (indicated by the parameter)
    > + * then it is the caller's responsibility to commit it.
    > + */
    > +bool
    > +FetchRelationStates(bool *started_tx)
    >
    > Here is another place where the function name is "relations", but the
    > function comment refers to "tables".
    
    In this place the use of tables in comment is intentional, as the
    return is based on subscription having any tables, and is not
    applicable for sequence.
    
    The rest of the comments are fixed and the changes for the same are
    available at the v202412123 version patch shared at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm0FqKMqOdm7tNoT5KgK1BAMeeVnOXrSJ2024TscAbf4Og%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  182. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-12-25T03:44:11Z

    On Fri, 20 Dec 2024 at 06:27, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Here are some review comments for the patch v20241211-0004.
    >
    > ======
    > GENERAL
    >
    > 1.
    > There are more than a dozen places where the relation (relkind) is
    > checked to see if it is a SEQUENCE:
    >
    > e.g. + get_rel_relkind(subrel->srrelid) != RELKIND_SEQUENCE &&
    > e.g. + if (get_rel_relkind(subrel->srrelid) != RELKIND_SEQUENCE)
    > e.g. + if (relkind == RELKIND_SEQUENCE && !get_sequences)
    > e.g. + if (relkind != RELKIND_SEQUENCE && !get_tables)
    > e.g. + relkind == RELKIND_SEQUENCE ? "sequence" : "table",
    > e.g. + if (relkind != RELKIND_SEQUENCE)
    > e.g. + relkind == RELKIND_SEQUENCE ? "sequence" : "table",
    > e.g. + if (get_rel_relkind(sub_remove_rels[off].relid) == RELKIND_SEQUENCE)
    > e.g. + if (get_rel_relkind(relid) != RELKIND_SEQUENCE)
    > e.g. + relkind != RELKIND_SEQUENCE)
    > e.g. + Assert(get_rel_relkind(rstate->relid) == RELKIND_SEQUENCE);
    > e.g. + Assert(relkind == RELKIND_SEQUENCE);
    > e.g. + if (get_rel_relkind(rstate->relid) == RELKIND_SEQUENCE)
    > e.g. + Assert(get_rel_relkind(rstate->relid) != RELKIND_SEQUENCE);
    >
    > I am wondering if the code might be improved slightly by adding one new macro:
    >
    > #define RELKIND_IS_SEQUENCE(relkind) ((relkind) == RELKIND_SEQUENCE)
    
    I was not sure of this, as it is being done like that in other parts
    of code like in aclchk.c, should we try to do this change as a
    separate patch.
    
    >
    > 12.
    > - logicalrep_worker_stop(w->subid, w->relid);
    > + /* Worker might have exited because of an error */
    > + if (w->type == WORKERTYPE_UNKNOWN)
    > + continue;
    > +
    > + logicalrep_worker_stop(w->subid, w->relid, w->type);
    >
    > It may be better to put that special case WORKERTYPE_UNKNOWN condition
    > as a quick exit within the logicalrep_worker_stop() function.
    
    I have removed this as this will be handled by logicalrep_worker_stop
    as the Assert is now removed.
    
    > ======
    > src/backend/replication/logical/launcher.c
    >
    > logicalrep_worker_find:
    >
    > 13.
    > + Assert(wtype == WORKERTYPE_TABLESYNC ||
    > +    wtype == WORKERTYPE_SEQUENCESYNC ||
    > +    wtype == WORKERTYPE_APPLY);
    > +
    >
    > The master version of this function checked for
    > isParallelApplyWorker(w), but now if a WORKERTYPE_PARALLEL_APPLY ever
    > got to here it would fail the above Assert. So, is the patch code OK,
    > or do we still need to also account for a possible
    > WORKERTYPE_PARALLEL_APPLY reaching here?
    
    I have removed this assertion and kept it as in master code.
    
    > ~~~
    >
    > logicalrep_worker_stop:
    >
    > 14.
    > worker = logicalrep_worker_find(subid, relid, wtype, false);
    >
    > if (worker)
    > {
    >   Assert(!isParallelApplyWorker(worker));
    >   logicalrep_worker_stop_internal(worker, SIGTERM);
    > }
    >
    > ~
    >
    > This code is not changed much from before, so it first finds the
    > worker, but then asserts that it must not be not a parallel apply
    > worker. But now, since the wtype is known and passed to the function
    > why not move the Assert up-front based on the wtype and before even
    > doing the 'find'?
    
    I prefer to keep it the way currently it is, as in_use also is
    required to be checked apart from worker type.
    
    
    > FetchRelationStates:
    >
    > 23.
    > - * Note: If this function started the transaction (indicated by the parameter)
    > - * then it is the caller's responsibility to commit it.
    > + * Returns true if subscription has 1 or more tables, else false.
    >   */
    >  bool
    > -FetchRelationStates(bool *started_tx)
    > +FetchRelationStates(void)
    >
    > Partly because of the name (relations), I felt this might be better to
    > be a void function and the returned value would be passed back by
    > references (bool *has_tables).
    
    I did not want to add it as a function parameter, as this value is not
    required in all the callers like the caller SyncProcessRelations.
    Instead I have changed the variable to has_tables in this caller
    function to avoid confusion.
    
    > ======
    > src/backend/replication/logical/worker.c
    >
    > SetupApplyOrSyncWorker:
    >
    > 24.
    > +
    > + if (am_sequencesync_worker())
    > + before_shmem_exit(logicalrep_seqsyncworker_failuretime, (Datum) 0);
    >
    > There should be a comment saying what this callback is for.
    
    Function logicalrep_seqsyncworker_failuretime mentions it updates the
    failure time. Function ProcessSyncingSequencesForApply mentions the
    reason:
     * To prevent starting the sequencesync worker at a high frequency after a
     * failure, we store its last failure time. We start the sequencesync worker
     * again after waiting at least wal_retrieve_retry_interval.
    
    I felt this should be enough.
    
    The rest of the comments are fixed. The attached patch has the changes
    for the same.
    
    Regards,
    Vignesh
    
  183. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-12-25T03:46:46Z

    On Fri, 20 Dec 2024 at 08:05, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh.
    >
    > Here are some review comments for the patch v20241211-0005.
    >
    > ======
    >
    > Section "29.6.3. Examples"
    >
    > 2.
    > Should the Examples section also have an example of ALTER SUBSCRIPTION
    > ... REFRESH PUBLICATION to demonstrate (like in the TAP tests) that if
    > the sequences are already known, then those are not synchronised?
    
    I felt it is not required, let's not add too many examples.
    
    > Section "29.8. Restrictions"
    >
    > 3.
    > +     Incremental sequence changes are not replicated.  The data in serial or
    > +     identity columns backed by sequences will of course be replicated as part
    > +     of the table, but the sequence itself would still show the start value on
    > +     the subscriber.  If the subscriber is used as a read-only database, then
    > +     this should typically not be a problem.  If, however, some kind of
    > +     switchover or failover to the subscriber database is intended, then the
    > +     sequences would need to be updated to the latest values, either
    > by executing
    > +     <link linkend="sql-altersubscription-params-refresh-publication-sequences">
    > +     <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > SEQUENCES</command></link>
    > +     or by copying the current data from the publisher (perhaps using
    > +     <command>pg_dump</command>) or by determining a sufficiently high value
    > +     from the tables themselves.
    >
    > I don't know if you need to mention it, or maybe it is too obvious,
    > but the suggestion here to use "ALTER SUBSCRIPTION ... REFRESH
    > PUBLICATION SEQUENCES" assumed you've already arranged for the
    > PUBLICATION to be publishing sequences before this.
    
    I felt it is obvious, it need not be mentioned.
    
    > ======
    > doc/src/sgml/ref/alter_subscription.sgml
    >
    > 4.
    >           <para>
    > -          Specifies whether to copy pre-existing data in the publications
    > -          that are being subscribed to when the replication starts.
    > -          The default is <literal>true</literal>.
    > +          Specifies whether to copy pre-existing data for tables and
    > synchronize
    > +          sequences in the publications that are being subscribed to
    > when the replication
    > +          starts. The default is <literal>true</literal>.
    >           </para>
    >
    > This is talking also about "synchronize sequences" when the
    > replication starts, but it is a bit confusing. IIUC, the .. REFRESH
    > PUBLICATION only synchronizes *newly added* sequences anyway, so does
    > it mean even that will not happen if copy_data=false?
    >
    > I think this option needs more clarification on how it interacts with
    > sequences. Also, I don't recall seeing any test for sequences and
    > copy_data in the patch 0004 TAP tests, so maybe something needs to be
    > added there too.
    
    This case is similar to how tables are handled, that is add the table
    in subscription_rel and mark it as ready without updating the data.
    Since tables and sequences behave the same way I have kept the
    documentation the same. I have added a test for this in the 0004 TAP
    test.
    
    The rest of the comments are fixed and the changes for the same are
    available in the v202412125 version patch at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm0PbSAQvs34D%2BJ63SgmRUzDQHZ1W4aeW_An9pR_tXJnRA%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  184. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2024-12-27T09:48:33Z

    Dear Vignesh,
    
    Thanks for updating the patch! Here are my comments.
    
    01. SyncingRelationsState
    
    ```
     * SYNC_RELATIONS_STATE_NEEDS_REBUILD The subscription relations state is no
     * longer valid and the subscription relations should be rebuilt.
    ```
    
    Can we follow the style like other lines? Like:
    
    SYNC_RELATIONS_STATE_NEEDS_REBUILD indicates that the subscription relations
    state is no longer valid and the subscription relations should be rebuilt.
    
    02. FetchRelationStates()
    
    ```
    		/* Fetch tables and sequences that are in non-ready state. */
    		rstates = GetSubscriptionRelations(MySubscription->oid, true, true,
    										   false);
    ```
    
    I think rstates should be list_free_deep()'d after the foreach().
    
    03. LogicalRepSyncSequences
    
    ```
    	char		slotname[NAMEDATALEN];
    ...
    	snprintf(slotname, NAMEDATALEN, "pg_%u_sync_sequences_" UINT64_FORMAT,
    			 subid, GetSystemIdentifier());
    
    	/*
    	 * Here we use the slot name instead of the subscription name as the
    	 * application_name, so that it is different from the leader apply worker,
    	 * so that synchronous replication can distinguish them.
    	 */
    	LogRepWorkerWalRcvConn =
    		walrcv_connect(MySubscription->conninfo, true, true,
    					   must_use_password,
    					   slotname, &err);
    ```
    
    Hmm, IIUC the sequence sync worker does not require any replication slots.
    I feel the variable name should be "application_name" and the comment can be updated.
    
    04. LogicalRepSyncSequences
    
    ```
    	/* Get the sequences that should be synchronized. */
    	sequences = GetSubscriptionRelations(subid, false, true, false);
    ```
    
    I think rstates should be list_free_deep()'d after the foreach_ptr().
    
    05. LogicalRepSyncSequences
    
    ```
    		/*
    		 * COPY FROM does not honor RLS policies.  That is not a problem for
    		 * subscriptions owned by roles with BYPASSRLS privilege (or
    		 * superuser, who has it implicitly), but other roles should not be
    		 * able to circumvent RLS.  Disallow logical replication into RLS
    		 * enabled relations for such roles.
    		 */
    		if (check_enable_rls(RelationGetRelid(sequence_rel), InvalidOid, false) == RLS_ENABLED)
    			ereport(ERROR,
    					errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    					errmsg("user \"%s\" cannot replicate into sequence with row-level security enabled: \"%s\"",
    						   GetUserNameFromId(GetUserId(), true),
    						   RelationGetRelationName(sequence_rel)));
    ```
    
    Can we really set a row level security policy to sequences? I've tested but
    I couldn't.
    
    ```
    postgres=# CREATE SEQUENCE s;
    CREATE SEQUENCE
    postgres=# ALTER TABLE s ENABLE ROW LEVEL SECURITY ;
    ERROR:  ALTER action ENABLE ROW SECURITY cannot be performed on relation "s"
    DETAIL:  This operation is not supported for sequences.
    ```
    
    06. copy_sequence
    
    ```
    	appendStringInfo(&cmd, "SELECT c.oid, c.relkind\n"
    					 "FROM pg_catalog.pg_class c\n"
    					 "INNER JOIN pg_catalog.pg_namespace n\n"
    					 "  ON (c.relnamespace = n.oid)\n"
    					 "WHERE n.nspname = %s AND c.relname = %s",
    					 quote_literal_cstr(nspname),
    					 quote_literal_cstr(relname));
    ```
    
    I feel the function is not so efficient because it can obtain only a tuple, i.e.,
    information for one sequence at once. I think you basically copied from fetch_remote_table_info(),
    but it was OK for it because the tablesync worker handles only a table.
    
    Can you obtain all sequences at once and check whether each sequences match or not?
    
    07. LogicalRepSyncSequences
    
    ```
    			/* LOG all the sequences synchronized during current batch. */
    			for (int i = 0; i < curr_batch_seq; i++)
    			{
    				SubscriptionRelState *done_seq;
    
    				done_seq = (SubscriptionRelState *) lfirst(list_nth_cell(sequences_not_synced,
    																		 (curr_seq - curr_batch_seq) + i));
    
    				ereport(DEBUG1,
    						errmsg_internal("logical replication synchronization for subscription \"%s\", sequence \"%s\" has finished",
    										get_subscription_name(subid, false), get_rel_name(done_seq->relid)));
    			}
    ```
    
    The loop is needed only when the debug messages should be output the system.
    Can we use message_level_is_interesting() to skip the loop for some cases?
    
    08. pg_dump.c
    
    ```
    /*
     * getSubscriptionTables
     *	  Get information about subscription membership for dumpable tables. This
     *    will be used only in binary-upgrade mode for PG17 or later versions.
     */
    void
    getSubscriptionTables(Archive *fout)
    ```
    
    I was bit confused of the pg_dump codes. I doubt that the pg_upgrade might not
    be able to transfer pg_subscripion_rel entries of sequences, but it seemed to work
    well because sequences are handled mostly same as normal tables on the pg_dump layer.
    But based on other codes, the function should be "getSubscriptionRelations" and
    comments should be also updated.
    
    09. logical-replication.sgml
    
    I feel we can add descriptions in "Publication" section. E.g.: 
    
    Publications can also include sequences, but the behavior differs from a table
    or a group of tables: users can synchronize current states of sequences at an
    arbitrary timing. For more details, please see "Replicating Sequences".
    
    10. pg_proc.dat
    
    ```
    +{ oid => '6313',
    +  descr => 'current on-disk sequence state',
    +  proname => 'pg_sequence_state', provolatile => 'v',
    +  prorettype => 'record', proargtypes => 'regclass',
    +  proallargtypes => '{regclass,pg_lsn,int8,int8,bool}',
    +  proargmodes => '{i,o,o,o,o}',
    +  proargnames => '{seq_oid,page_lsn,last_value,log_cnt,is_called}',
    +  prosrc => 'pg_sequence_state' },
    ```
    
    I think this is not wrong, but according to the src/include/catalog/unused_oids,
    the oid should be at 8000-9999 while developing:
    
    ```
    $ ./unused_oids
    ...
    Patches should use a more-or-less consecutive range of OIDs.
    Best practice is to start with a random choice in the range 8000-9999.
    Suggested random unused OID: 9293 (415 consecutive OID(s) available starting here)
    ```
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
  185. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2024-12-30T10:10:14Z

    On Fri, 27 Dec 2024 at 15:18, Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > Dear Vignesh,
    >
    > Thanks for updating the patch! Here are my comments.
    >
    > 01. SyncingRelationsState
    >
    > ```
    >  * SYNC_RELATIONS_STATE_NEEDS_REBUILD The subscription relations state is no
    >  * longer valid and the subscription relations should be rebuilt.
    > ```
    >
    > Can we follow the style like other lines? Like:
    >
    > SYNC_RELATIONS_STATE_NEEDS_REBUILD indicates that the subscription relations
    > state is no longer valid and the subscription relations should be rebuilt.
    
    Modfied
    
    > 02. FetchRelationStates()
    >
    > ```
    >                 /* Fetch tables and sequences that are in non-ready state. */
    >                 rstates = GetSubscriptionRelations(MySubscription->oid, true, true,
    >                                                                                    false);
    > ```
    >
    > I think rstates should be list_free_deep()'d after the foreach().
    
    Since rstates is allocated in TopTransactionContext and there is a
    CommitTransactionCommand which will take care of releasing the memory
    from AtCommit_Memory:
            /*
             * Release all transaction-local memory.  TopTransactionContext survives
             * but becomes empty; any sub-contexts go away.
             */
            Assert(TopTransactionContext != NULL);
            MemoryContextReset(TopTransactionContext);
    
    So I felt deep free is not required in this case.
    
    > 03. LogicalRepSyncSequences
    >
    > ```
    >         char            slotname[NAMEDATALEN];
    > ...
    >         snprintf(slotname, NAMEDATALEN, "pg_%u_sync_sequences_" UINT64_FORMAT,
    >                          subid, GetSystemIdentifier());
    >
    >         /*
    >          * Here we use the slot name instead of the subscription name as the
    >          * application_name, so that it is different from the leader apply worker,
    >          * so that synchronous replication can distinguish them.
    >          */
    >         LogRepWorkerWalRcvConn =
    >                 walrcv_connect(MySubscription->conninfo, true, true,
    >                                            must_use_password,
    >                                            slotname, &err);
    > ```
    >
    > Hmm, IIUC the sequence sync worker does not require any replication slots.
    > I feel the variable name should be "application_name" and the comment can be updated.
    
    Modified
    
    > 04. LogicalRepSyncSequences
    >
    > ```
    >         /* Get the sequences that should be synchronized. */
    >         sequences = GetSubscriptionRelations(subid, false, true, false);
    > ```
    >
    > I think rstates should be list_free_deep()'d after the foreach_ptr().
    
    Since rstates is allocated in TopTransactionContext and there is a
    CommitTransactionCommand immediately which will take care of releasing
    the memory from AtCommit_Memory:
            /*
             * Release all transaction-local memory.  TopTransactionContext survives
             * but becomes empty; any sub-contexts go away.
             */
            Assert(TopTransactionContext != NULL);
            MemoryContextReset(TopTransactionContext);
    
    So I felt deep free is not required in this case.
    
    > 05. LogicalRepSyncSequences
    >
    > ```
    >                 /*
    >                  * COPY FROM does not honor RLS policies.  That is not a problem for
    >                  * subscriptions owned by roles with BYPASSRLS privilege (or
    >                  * superuser, who has it implicitly), but other roles should not be
    >                  * able to circumvent RLS.  Disallow logical replication into RLS
    >                  * enabled relations for such roles.
    >                  */
    >                 if (check_enable_rls(RelationGetRelid(sequence_rel), InvalidOid, false) == RLS_ENABLED)
    >                         ereport(ERROR,
    >                                         errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    >                                         errmsg("user \"%s\" cannot replicate into sequence with row-level security enabled: \"%s\"",
    >                                                    GetUserNameFromId(GetUserId(), true),
    >                                                    RelationGetRelationName(sequence_rel)));
    > ```
    >
    > Can we really set a row level security policy to sequences? I've tested but
    > I couldn't.
    >
    > ```
    > postgres=# CREATE SEQUENCE s;
    > CREATE SEQUENCE
    > postgres=# ALTER TABLE s ENABLE ROW LEVEL SECURITY ;
    > ERROR:  ALTER action ENABLE ROW SECURITY cannot be performed on relation "s"
    > DETAIL:  This operation is not supported for sequences.
    > ```
    
    Removed this check
    
    > 06. copy_sequence
    >
    > ```
    >         appendStringInfo(&cmd, "SELECT c.oid, c.relkind\n"
    >                                          "FROM pg_catalog.pg_class c\n"
    >                                          "INNER JOIN pg_catalog.pg_namespace n\n"
    >                                          "  ON (c.relnamespace = n.oid)\n"
    >                                          "WHERE n.nspname = %s AND c.relname = %s",
    >                                          quote_literal_cstr(nspname),
    >                                          quote_literal_cstr(relname));
    > ```
    >
    > I feel the function is not so efficient because it can obtain only a tuple, i.e.,
    > information for one sequence at once. I think you basically copied from fetch_remote_table_info(),
    > but it was OK for it because the tablesync worker handles only a table.
    >
    > Can you obtain all sequences at once and check whether each sequences match or not?
    
    I still could not come up with a simple way to do this, I will think
    more and handle this in the next version.
    
    > 07. LogicalRepSyncSequences
    >
    > ```
    >                         /* LOG all the sequences synchronized during current batch. */
    >                         for (int i = 0; i < curr_batch_seq; i++)
    >                         {
    >                                 SubscriptionRelState *done_seq;
    >
    >                                 done_seq = (SubscriptionRelState *) lfirst(list_nth_cell(sequences_not_synced,
    >                                                                                                                                                  (curr_seq - curr_batch_seq) + i));
    >
    >                                 ereport(DEBUG1,
    >                                                 errmsg_internal("logical replication synchronization for subscription \"%s\", sequence \"%s\" has finished",
    >                                                                                 get_subscription_name(subid, false), get_rel_name(done_seq->relid)));
    >                         }
    > ```
    >
    > The loop is needed only when the debug messages should be output the system.
    > Can we use message_level_is_interesting() to skip the loop for some cases?
    
    Modified
    
    > 08. pg_dump.c
    >
    > ```
    > /*
    >  * getSubscriptionTables
    >  *        Get information about subscription membership for dumpable tables. This
    >  *    will be used only in binary-upgrade mode for PG17 or later versions.
    >  */
    > void
    > getSubscriptionTables(Archive *fout)
    > ```
    >
    > I was bit confused of the pg_dump codes. I doubt that the pg_upgrade might not
    > be able to transfer pg_subscripion_rel entries of sequences, but it seemed to work
    > well because sequences are handled mostly same as normal tables on the pg_dump layer.
    > But based on other codes, the function should be "getSubscriptionRelations" and
    > comments should be also updated.
    
    Modified
    
    > 09. logical-replication.sgml
    >
    > I feel we can add descriptions in "Publication" section. E.g.:
    >
    > Publications can also include sequences, but the behavior differs from a table
    > or a group of tables: users can synchronize current states of sequences at an
    > arbitrary timing. For more details, please see "Replicating Sequences".
    
    Added this
    
    > 10. pg_proc.dat
    >
    > ```
    > +{ oid => '6313',
    > +  descr => 'current on-disk sequence state',
    > +  proname => 'pg_sequence_state', provolatile => 'v',
    > +  prorettype => 'record', proargtypes => 'regclass',
    > +  proallargtypes => '{regclass,pg_lsn,int8,int8,bool}',
    > +  proargmodes => '{i,o,o,o,o}',
    > +  proargnames => '{seq_oid,page_lsn,last_value,log_cnt,is_called}',
    > +  prosrc => 'pg_sequence_state' },
    > ```
    >
    > I think this is not wrong, but according to the src/include/catalog/unused_oids,
    > the oid should be at 8000-9999 while developing:
    >
    > ```
    > $ ./unused_oids
    > ...
    > Patches should use a more-or-less consecutive range of OIDs.
    > Best practice is to start with a random choice in the range 8000-9999.
    > Suggested random unused OID: 9293 (415 consecutive OID(s) available starting here)
    > ```
    
    Modified
    
    Thanks for the comments, the attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  186. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-01-03T01:22:30Z

    Hi Vignesh.
    
    Here are some review comments for patch v20241230-0002
    
    ======
    1. SYNTAX
    
    The proposed syntax is currently:
    
    CREATE PUBLICATION name
        [ FOR ALL object_type [, ...]
          | FOR publication_object [, ... ] ]
        [ WITH ( publication_parameter [= value] [, ... ] ) ]
    
    where object_type is one of:
    
        TABLES
        SEQUENCES
    
    where publication_object is one of:
    
        TABLE [ ONLY ] table_name [ * ] [ ( column_name [, ... ] ) ] [
    WHERE ( expression ) ] [, ... ]
        TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ]
    ~
    
    But lately, I've been thinking it could be clearer if you removed the
    object_type and instead fully spelled out FOR ALL TABLES and/or FOR
    ALL SEQUENCES.
    
    compare
    CREATE PUBLICATION FOR ALL TABLES, SEQUENCES;
    versus
    CREATE PUBLICATION FOR ALL TABLES, ALL SEQUENCES;
    
    ~
    
    Also AFAICT, the current syntax says it is impossible to mix FOR ALL
    SEQUENCES with FOR TABLE etc but really that *should* be allowed,
    right?
    
    And it looks like you may come to similar grief in future if you try
    things like:
    "FOR ALL TABLES" mixed with "FOR SEQUENCE seq_name"
    "FOR ALL TABLES" mixed with "FOR SEQUENCES IN SCHEMA schema_name"
    
    ~
    
    So, maybe a revised syntax like below would end up being easier and
    also more flexible:
    
    CREATE PUBLICATION name
        [ FOR publication_object [, ... ] ]
        [ WITH ( publication_parameter [= value] [, ... ] ) ]
    
    where publication_object is one of:
    
        ALL TABLES
        ALL SEQUENCES
        TABLE [ ONLY ] table_name [ * ] [ ( column_name [, ... ] ) ] [
    WHERE ( expression ) ] [, ... ]
        TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ]
    
    ======
    src/backend/commands/publicationcmds.c
    
    CreatePublication:
    
    2.
    - /* FOR ALL TABLES requires superuser */
    - if (stmt->for_all_tables && !superuser())
    + /* FOR ALL TABLES or FOR ALL SEQUENCES requires superuser */
    + if ((stmt->for_all_tables || stmt->for_all_sequences) && !superuser())
      ereport(ERROR,
      (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    - errmsg("must be superuser to create FOR ALL TABLES publication")));
    + errmsg("must be superuser to create ALL TABLES and/or ALL SEQUENCES
    publication")));
    
    
    2a.
    Typo.
    
    /create ALL TABLES and/or ALL SEQUENCES publication/create a FOR ALL
    TABLES and/or a FOR ALL SEQUENCES publication/
    
    ~
    
    2b.
    This message might be OK now, but I suspect it will become very messy
    in future after you introduce another syntax like "FOR SEQUENCE
    seq_name" etc (which would also be able to be used in combination with
    a FOR ALL TABLES).
    
    So, I think that for future-proofing against all the possible (future)
    combinations, and for keeping the code cleaner, it will be far simpler
    to just keep the errors for tables and sequences separated:
    
    SUGGESTION:
    if (!superuser())
    {
      if (stmt->for_all_tables)
        ereport(ERROR, ... FOR ALL TABLES ...);
      if (stmt->for_all_sequences)
        ereport(ERROR, ... FOR ALL SEQUENCES ...);
    }
    
    ~~~
    
    AlterPublicationOwner_internal:
    
    3.
    - if (form->puballtables && !superuser_arg(newOwnerId))
    + /* FOR ALL TABLES or FOR ALL SEQUENCES requires superuser */
    + if ((form->puballtables || form->puballsequences) &&
    + !superuser_arg(newOwnerId))
      ereport(ERROR,
      (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
      errmsg("permission denied to change owner of publication \"%s\"",
      NameStr(form->pubname)),
    - errhint("The owner of a FOR ALL TABLES publication must be a superuser.")));
    + errhint("The owner of ALL TABLES and/or ALL SEQUENCES publication
    must be a superuser.")));
    
    Ditto the above comment #2.
    
    ======
    src/bin/psql/describe.c
    
    4.
    + puboid_col = cols++;
    + pubname_col = cols++;
    + pubowner_col = cols++;
    + puballtables_col = cols++;
    +
    + if (has_pubsequence)
    + {
    + appendPQExpBufferStr(&buf,
    + ", puballsequences");
    + puballsequences_col = cols++;
    + }
    +
    + appendPQExpBufferStr(&buf,
    + ", pubinsert, pubupdate, pubdelete");
    + pubins_col = cols++;
    + pubupd_col = cols++;
    + pubdel_col = cols++;
    +
      if (has_pubtruncate)
    + {
      appendPQExpBufferStr(&buf,
      ", pubtruncate");
    + pubtrunc_col = cols++;
    + }
    +
      if (has_pubgencols)
    + {
      appendPQExpBufferStr(&buf,
      ", pubgencols");
    + pubgen_col = cols++;
    + }
    +
      if (has_pubviaroot)
    + {
      appendPQExpBufferStr(&buf,
      ", pubviaroot");
    + pubviaroot_col = cols++;
    + }
    
    There is some overlap/duplication of the new variable 'cols' and the
    existing variable 'ncols'.
    
    AFAICT you can just move/replace the declaration of 'ncols' to where
    'cols' is declared, and then you can remove the duplicated code below
    (because the above code is already doing the same thing).
    
    if (has_pubtruncate)
      ncols++;
    if (has_pubgencols)
      ncols++;
    if (has_pubviaroot)
      ncols++;
    if (has_pubsequence)
      ncols++;
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  187. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-01-03T03:37:28Z

    Hi Vignesh,
    
    Some minor review comments for the patch v20241230-0003.
    
    ======
    src/backend/replication/logical/syncutils.c
    
    1.
    + * syncutils.c
    + *   PostgreSQL logical replication: common synchronization code
    + *
    + * Copyright (c) 2024, PostgreSQL Global Development Group
    
    Happy New Year.
    
    s/2024/2025/
    
    ~~~
    
    2.
    +/*
    + * Enum representing the overall state of subscription relations state.
    + *
    + * SYNC_RELATIONS_STATE_NEEDS_REBUILD indicates that the subscription relations
    + * state is no longer valid and the subscription relations should be rebuilt.
    + *
    + * SYNC_RELATIONS_STATE_REBUILD_STARTED indicates that the subscription
    + * relations state is being rebuilt.
    + *
    + * SYNC_RELATIONS_STATE_VALID indicates that subscription relation state is
    + * up-to-date and valid.
    + */
    
    2a.
    That first sentence saying "overall state of [...] state" is a bit strange.
    
    Maybe it can be reworded something like:
    Enum for phases of the subscription relations state.
    
    ~
    
    2b.
    /is no longer valid and/is no longer valid, and/
    
    `
    
    2c.
    /that subscription relation state is up-to-date/that the subscription
    relation state is up-to-date/
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  188. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-01-04T04:31:07Z

    On Fri, 3 Jan 2025 at 06:53, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh.
    >
    > Here are some review comments for patch v20241230-0002
    >
    > ======
    > 1. SYNTAX
    >
    > The proposed syntax is currently:
    >
    > CREATE PUBLICATION name
    >     [ FOR ALL object_type [, ...]
    >       | FOR publication_object [, ... ] ]
    >     [ WITH ( publication_parameter [= value] [, ... ] ) ]
    >
    > where object_type is one of:
    >
    >     TABLES
    >     SEQUENCES
    >
    > where publication_object is one of:
    >
    >     TABLE [ ONLY ] table_name [ * ] [ ( column_name [, ... ] ) ] [
    > WHERE ( expression ) ] [, ... ]
    >     TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ]
    > ~
    >
    > But lately, I've been thinking it could be clearer if you removed the
    > object_type and instead fully spelled out FOR ALL TABLES and/or FOR
    > ALL SEQUENCES.
    >
    > compare
    > CREATE PUBLICATION FOR ALL TABLES, SEQUENCES;
    > versus
    > CREATE PUBLICATION FOR ALL TABLES, ALL SEQUENCES;
    >
    > ~
    >
    > Also AFAICT, the current syntax says it is impossible to mix FOR ALL
    > SEQUENCES with FOR TABLE etc but really that *should* be allowed,
    > right?
    >
    > And it looks like you may come to similar grief in future if you try
    > things like:
    > "FOR ALL TABLES" mixed with "FOR SEQUENCE seq_name"
    > "FOR ALL TABLES" mixed with "FOR SEQUENCES IN SCHEMA schema_name"
    >
    > ~
    >
    > So, maybe a revised syntax like below would end up being easier and
    > also more flexible:
    >
    > CREATE PUBLICATION name
    >     [ FOR publication_object [, ... ] ]
    >     [ WITH ( publication_parameter [= value] [, ... ] ) ]
    >
    > where publication_object is one of:
    >
    >     ALL TABLES
    >     ALL SEQUENCES
    >     TABLE [ ONLY ] table_name [ * ] [ ( column_name [, ... ] ) ] [
    > WHERE ( expression ) ] [, ... ]
    >     TABLES IN SCHEMA { schema_name | CURRENT_SCHEMA } [, ... ]
    
    The proposed be more easier to extend the syntax in the future, so
    modified.The proposed be more easier to extend the syntax in the
    future, so modified.
    
    > ======
    > src/backend/commands/publicationcmds.c
    >
    > CreatePublication:
    >
    > 2.
    > - /* FOR ALL TABLES requires superuser */
    > - if (stmt->for_all_tables && !superuser())
    > + /* FOR ALL TABLES or FOR ALL SEQUENCES requires superuser */
    > + if ((stmt->for_all_tables || stmt->for_all_sequences) && !superuser())
    >   ereport(ERROR,
    >   (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    > - errmsg("must be superuser to create FOR ALL TABLES publication")));
    > + errmsg("must be superuser to create ALL TABLES and/or ALL SEQUENCES
    > publication")));
    >
    >
    > 2a.
    > Typo.
    >
    > /create ALL TABLES and/or ALL SEQUENCES publication/create a FOR ALL
    > TABLES and/or a FOR ALL SEQUENCES publication/
    
    Modified
    
    > ~
    >
    > 2b.
    > This message might be OK now, but I suspect it will become very messy
    > in future after you introduce another syntax like "FOR SEQUENCE
    > seq_name" etc (which would also be able to be used in combination with
    > a FOR ALL TABLES).
    >
    > So, I think that for future-proofing against all the possible (future)
    > combinations, and for keeping the code cleaner, it will be far simpler
    > to just keep the errors for tables and sequences separated:
    >
    > SUGGESTION:
    > if (!superuser())
    > {
    >   if (stmt->for_all_tables)
    >     ereport(ERROR, ... FOR ALL TABLES ...);
    >   if (stmt->for_all_sequences)
    >     ereport(ERROR, ... FOR ALL SEQUENCES ...);
    > }
    
    If we do that way it will not print both the stmt publication type if
    both "ALL TABLES" and "ALL SEQUENCES" is specified.
    
    > ~~~
    >
    > AlterPublicationOwner_internal:
    >
    > 3.
    > - if (form->puballtables && !superuser_arg(newOwnerId))
    > + /* FOR ALL TABLES or FOR ALL SEQUENCES requires superuser */
    > + if ((form->puballtables || form->puballsequences) &&
    > + !superuser_arg(newOwnerId))
    >   ereport(ERROR,
    >   (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    >   errmsg("permission denied to change owner of publication \"%s\"",
    >   NameStr(form->pubname)),
    > - errhint("The owner of a FOR ALL TABLES publication must be a superuser.")));
    > + errhint("The owner of ALL TABLES and/or ALL SEQUENCES publication
    > must be a superuser.")));
    >
    > Ditto the above comment #2.
    
    Modified the message
    
    > ======
    > src/bin/psql/describe.c
    >
    > 4.
    > + puboid_col = cols++;
    > + pubname_col = cols++;
    > + pubowner_col = cols++;
    > + puballtables_col = cols++;
    > +
    > + if (has_pubsequence)
    > + {
    > + appendPQExpBufferStr(&buf,
    > + ", puballsequences");
    > + puballsequences_col = cols++;
    > + }
    > +
    > + appendPQExpBufferStr(&buf,
    > + ", pubinsert, pubupdate, pubdelete");
    > + pubins_col = cols++;
    > + pubupd_col = cols++;
    > + pubdel_col = cols++;
    > +
    >   if (has_pubtruncate)
    > + {
    >   appendPQExpBufferStr(&buf,
    >   ", pubtruncate");
    > + pubtrunc_col = cols++;
    > + }
    > +
    >   if (has_pubgencols)
    > + {
    >   appendPQExpBufferStr(&buf,
    >   ", pubgencols");
    > + pubgen_col = cols++;
    > + }
    > +
    >   if (has_pubviaroot)
    > + {
    >   appendPQExpBufferStr(&buf,
    >   ", pubviaroot");
    > + pubviaroot_col = cols++;
    > + }
    >
    > There is some overlap/duplication of the new variable 'cols' and the
    > existing variable 'ncols'.
    >
    > AFAICT you can just move/replace the declaration of 'ncols' to where
    > 'cols' is declared, and then you can remove the duplicated code below
    > (because the above code is already doing the same thing).
    >
    > if (has_pubtruncate)
    >   ncols++;
    > if (has_pubgencols)
    >   ncols++;
    > if (has_pubviaroot)
    >   ncols++;
    > if (has_pubsequence)
    >   ncols++;
    
    I have removed ncols and used cols.
    
    The attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  189. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-01-04T04:33:24Z

    On Fri, 3 Jan 2025 at 09:07, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Some minor review comments for the patch v20241230-0003.
    >
    > ======
    > src/backend/replication/logical/syncutils.c
    >
    > 1.
    > + * syncutils.c
    > + *   PostgreSQL logical replication: common synchronization code
    > + *
    > + * Copyright (c) 2024, PostgreSQL Global Development Group
    >
    > Happy New Year.
    >
    > s/2024/2025/
    
    Modified
    
    > ~~~
    >
    > 2.
    > +/*
    > + * Enum representing the overall state of subscription relations state.
    > + *
    > + * SYNC_RELATIONS_STATE_NEEDS_REBUILD indicates that the subscription relations
    > + * state is no longer valid and the subscription relations should be rebuilt.
    > + *
    > + * SYNC_RELATIONS_STATE_REBUILD_STARTED indicates that the subscription
    > + * relations state is being rebuilt.
    > + *
    > + * SYNC_RELATIONS_STATE_VALID indicates that subscription relation state is
    > + * up-to-date and valid.
    > + */
    >
    > 2a.
    > That first sentence saying "overall state of [...] state" is a bit strange.
    >
    > Maybe it can be reworded something like:
    > Enum for phases of the subscription relations state.
    
    Modified
    
    > ~
    >
    > 2b.
    > /is no longer valid and/is no longer valid, and/
    
    Modified
    
    >
    > 2c.
    > /that subscription relation state is up-to-date/that the subscription
    > relation state is up-to-date/
    
    Modified
    
    The changes for the same are available at the v20250204 version patch
    attached at [1].
    
    [1] - https://www.postgresql.org/message-id/CALDaNm07EtT7zQXhjvaX7AKUv_gKMsrSYxJQmmOHhpCZpvV07w%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  190. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-01-06T05:15:51Z

    Hi Vignesh,
    
    FYI, looks like your attached patchset was misnamed 20250204 instead
    of 20250104. Anyway, it does not affect the reviews, but I am going to
    refer to it as 0104 from now.
    
    ~~~
    
    I have no comments for the patch v20250104-0001.
    
    Some comments for the patch v20250104-0002.
    
    ======
    doc/src/sgml/ref/create_publication.sgml
    
    1.
     <phrase>where <replaceable
    class="parameter">publication_object</replaceable> is one of:</phrase>
    
    +    ALL TABLES
    +    ALL SEQUENCES
         TABLE [ ONLY ] <replaceable
    class="parameter">table_name</replaceable> [ * ] [ ( <replaceable
    class="parameter">column_name</replaceable> [, ... ] ) ] [ WHERE (
    <replaceable class="parameter">expression</replaceable> ) ] [, ... ]
         TABLES IN SCHEMA { <replaceable
    class="parameter">schema_name</replaceable> | CURRENT_SCHEMA } [, ...
    ]
    
    I'm wondering if it would be better to reorder these in the synopsis as:
    TABLE...
    TABLES IN SCHEMA...
    ALL TABLES
    ALL SEQUENCES
    
    Then it will match the same order as the parameters section.
    
    ======
    src/backend/commands/publicationcmds.c
    
    2.
    > > CreatePublication:
    > >
    > > 2.
    > > - /* FOR ALL TABLES requires superuser */
    > > - if (stmt->for_all_tables && !superuser())
    > > + /* FOR ALL TABLES or FOR ALL SEQUENCES requires superuser */
    > > + if ((stmt->for_all_tables || stmt->for_all_sequences) && !superuser())
    > >   ereport(ERROR,
    > >   (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    > > - errmsg("must be superuser to create FOR ALL TABLES publication")));
    > > + errmsg("must be superuser to create ALL TABLES and/or ALL SEQUENCES
    > > publication")));
    > >
    > >
    > > 2b.
    > > This message might be OK now, but I suspect it will become very messy
    > > in future after you introduce another syntax like "FOR SEQUENCE
    > > seq_name" etc (which would also be able to be used in combination with
    > > a FOR ALL TABLES).
    > >
    > > So, I think that for future-proofing against all the possible (future)
    > > combinations, and for keeping the code cleaner, it will be far simpler
    > > to just keep the errors for tables and sequences separated:
    > >
    > > SUGGESTION:
    > > if (!superuser())
    > > {
    > >   if (stmt->for_all_tables)
    > >     ereport(ERROR, ... FOR ALL TABLES ...);
    > >   if (stmt->for_all_sequences)
    > >     ereport(ERROR, ... FOR ALL SEQUENCES ...);
    > > }
    >
    > If we do that way it will not print both the stmt publication type if
    > both "ALL TABLES" and "ALL SEQUENCES" is specified.
    >
    
    Yes, I know, but AFAICT you're going to encounter this same kind of
    problem anyway with all the other combinations, where we only give an
    error for the first thing it finds wrong.
    
    For example,
    CREATE FOR ALL SEQUENCES, TABLES IN SCHEMA s1;
    
    That's going to report "must be superuser to create a FOR ALL TABLES
    and/or a FOR ALL SEQUENCES publication", but it's not going to say
    "must be superuser to create FOR TABLES IN SCHEMA publication".
    
    So, my point was, I guess we are not going to make error messages for
    every possible combination, so why are we making a special case by
    combining only the message for ALL TABLES and ALL SEQUENCES?
    
    ======
    src/bin/psql/describe.c
    
    3.
    + if (has_pubsequence)
    + printTableAddCell(&cont, PQgetvalue(res, i, puballsequences_col),
    false, false); /* all sequences */
    
    The comment ("/* all sequences */") doesn't seem necessary given the
    self-explanatory variable name. Also, none of the similar nearby code
    has comments like this.
    
    ======
    src/test/regress/expected/publication.out
    
    4.
    +--- Specifying both ALL TABLES and ALL SEQUENCES
    +SET client_min_messages = 'ERROR';
    +CREATE PUBLICATION regress_pub_for_allsequences_alltables FOR ALL
    SEQUENCES, ALL TABLES;
    
    
    Do you think you should test this both ways?
    e.g.1. FOR ALL SEQUENCES, ALL TABLES
    e.g.2. FOR ALL TABLES, ALL SEQUENCES
    
    ~~~
    
    5.
    +DROP PUBLICATION regress_pub_forallsequences1,
    regress_pub_forallsequences2, regress_pub_for_allsequences_alltables;
    +-- fail - Specifying ALL TABLES more than once
    +CREATE PUBLICATION regress_pub_for_allsequences_alltables FOR ALL
    SEQUENCES, ALL TABLES, ALL TABLES;
    +ERROR:  invalid publication object list
    +LINE 1: ...equences_alltables FOR ALL SEQUENCES, ALL TABLES, ALL TABLES...
    +                                                             ^
    +DETAIL:  TABLES can be specified only once.
    
    Should the DETAIL message say ALL TABLES instead of just TABLES?
    
    ~~~
    
    6.
    +-- fail - Specifying ALL SEQUENCES more than once
    +CREATE PUBLICATION regress_pub_for_allsequences_alltables FOR ALL
    SEQUENCES, ALL TABLES, ALL SEQUENCES;
    +ERROR:  invalid publication object list
    +LINE 1: ...equences_alltables FOR ALL SEQUENCES, ALL TABLES, ALL SEQUEN...
    +                                                             ^
    +DETAIL:  SEQUENCES can be specified only once.
    
    Should the DETAIL message say ALL SEQUENCES instead of just SEQUENCES?
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  191. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-01-10T14:37:50Z

    On Mon, 6 Jan 2025 at 10:46, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > FYI, looks like your attached patchset was misnamed 20250204 instead
    > of 20250104. Anyway, it does not affect the reviews, but I am going to
    > refer to it as 0104 from now.
    >
    > ~~~
    >
    > I have no comments for the patch v20250104-0001.
    >
    > Some comments for the patch v20250104-0002.
    >
    > ======
    > doc/src/sgml/ref/create_publication.sgml
    >
    > 1.
    >  <phrase>where <replaceable
    > class="parameter">publication_object</replaceable> is one of:</phrase>
    >
    > +    ALL TABLES
    > +    ALL SEQUENCES
    >      TABLE [ ONLY ] <replaceable
    > class="parameter">table_name</replaceable> [ * ] [ ( <replaceable
    > class="parameter">column_name</replaceable> [, ... ] ) ] [ WHERE (
    > <replaceable class="parameter">expression</replaceable> ) ] [, ... ]
    >      TABLES IN SCHEMA { <replaceable
    > class="parameter">schema_name</replaceable> | CURRENT_SCHEMA } [, ...
    > ]
    >
    > I'm wondering if it would be better to reorder these in the synopsis as:
    > TABLE...
    > TABLES IN SCHEMA...
    > ALL TABLES
    > ALL SEQUENCES
    >
    > Then it will match the same order as the parameters section.
    
    Modified
    
    > ======
    > src/backend/commands/publicationcmds.c
    >
    > 2.
    > > > CreatePublication:
    > > >
    > > > 2.
    > > > - /* FOR ALL TABLES requires superuser */
    > > > - if (stmt->for_all_tables && !superuser())
    > > > + /* FOR ALL TABLES or FOR ALL SEQUENCES requires superuser */
    > > > + if ((stmt->for_all_tables || stmt->for_all_sequences) && !superuser())
    > > >   ereport(ERROR,
    > > >   (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    > > > - errmsg("must be superuser to create FOR ALL TABLES publication")));
    > > > + errmsg("must be superuser to create ALL TABLES and/or ALL SEQUENCES
    > > > publication")));
    > > >
    > > >
    > > > 2b.
    > > > This message might be OK now, but I suspect it will become very messy
    > > > in future after you introduce another syntax like "FOR SEQUENCE
    > > > seq_name" etc (which would also be able to be used in combination with
    > > > a FOR ALL TABLES).
    > > >
    > > > So, I think that for future-proofing against all the possible (future)
    > > > combinations, and for keeping the code cleaner, it will be far simpler
    > > > to just keep the errors for tables and sequences separated:
    > > >
    > > > SUGGESTION:
    > > > if (!superuser())
    > > > {
    > > >   if (stmt->for_all_tables)
    > > >     ereport(ERROR, ... FOR ALL TABLES ...);
    > > >   if (stmt->for_all_sequences)
    > > >     ereport(ERROR, ... FOR ALL SEQUENCES ...);
    > > > }
    > >
    > > If we do that way it will not print both the stmt publication type if
    > > both "ALL TABLES" and "ALL SEQUENCES" is specified.
    > >
    >
    > Yes, I know, but AFAICT you're going to encounter this same kind of
    > problem anyway with all the other combinations, where we only give an
    > error for the first thing it finds wrong.
    >
    > For example,
    > CREATE FOR ALL SEQUENCES, TABLES IN SCHEMA s1;
    >
    > That's going to report "must be superuser to create a FOR ALL TABLES
    > and/or a FOR ALL SEQUENCES publication", but it's not going to say
    > "must be superuser to create FOR TABLES IN SCHEMA publication".
    >
    > So, my point was, I guess we are not going to make error messages for
    > every possible combination, so why are we making a special case by
    > combining only the message for ALL TABLES and ALL SEQUENCES?
    
    Modified
    
    > ======
    > src/bin/psql/describe.c
    >
    > 3.
    > + if (has_pubsequence)
    > + printTableAddCell(&cont, PQgetvalue(res, i, puballsequences_col),
    > false, false); /* all sequences */
    >
    > The comment ("/* all sequences */") doesn't seem necessary given the
    > self-explanatory variable name. Also, none of the similar nearby code
    > has comments like this.
    
    Modified
    
    > ======
    > src/test/regress/expected/publication.out
    >
    > 4.
    > +--- Specifying both ALL TABLES and ALL SEQUENCES
    > +SET client_min_messages = 'ERROR';
    > +CREATE PUBLICATION regress_pub_for_allsequences_alltables FOR ALL
    > SEQUENCES, ALL TABLES;
    >
    >
    > Do you think you should test this both ways?
    > e.g.1. FOR ALL SEQUENCES, ALL TABLES
    > e.g.2. FOR ALL TABLES, ALL SEQUENCES
    
    I feel it is not required
    
    > ~~~
    >
    > 5.
    > +DROP PUBLICATION regress_pub_forallsequences1,
    > regress_pub_forallsequences2, regress_pub_for_allsequences_alltables;
    > +-- fail - Specifying ALL TABLES more than once
    > +CREATE PUBLICATION regress_pub_for_allsequences_alltables FOR ALL
    > SEQUENCES, ALL TABLES, ALL TABLES;
    > +ERROR:  invalid publication object list
    > +LINE 1: ...equences_alltables FOR ALL SEQUENCES, ALL TABLES, ALL TABLES...
    > +                                                             ^
    > +DETAIL:  TABLES can be specified only once.
    >
    > Should the DETAIL message say ALL TABLES instead of just TABLES?
    
    Modified
    
    > ~~~
    >
    > 6.
    > +-- fail - Specifying ALL SEQUENCES more than once
    > +CREATE PUBLICATION regress_pub_for_allsequences_alltables FOR ALL
    > SEQUENCES, ALL TABLES, ALL SEQUENCES;
    > +ERROR:  invalid publication object list
    > +LINE 1: ...equences_alltables FOR ALL SEQUENCES, ALL TABLES, ALL SEQUEN...
    > +                                                             ^
    > +DETAIL:  SEQUENCES can be specified only once.
    >
    > Should the DETAIL message say ALL SEQUENCES instead of just SEQUENCES?
    
    Modified
    
    The attached v20250110 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  192. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-02-03T05:43:31Z

    On Fri, 10 Jan 2025 at 20:07, vignesh C <vignesh21@gmail.com> wrote:
    >
    > The attached v20250110 version patch has the changes for the same.
    
    The patch was not applying on top of HEAD because of recent commits,
    here is a rebased version.
    
    Regards,
    Vignesh
    
  193. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-03-12T03:44:05Z

    On Mon, 3 Feb 2025 at 11:13, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 10 Jan 2025 at 20:07, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached v20250110 version patch has the changes for the same.
    >
    > The patch was not applying on top of HEAD because of recent commits,
    > here is a rebased version.
    
    The patch was not applying on top of HEAD because of recent commits,
    here is a rebased version.
    
    Regards,
    Vignesh
    
  194. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-03-12T11:34:01Z

    On Wed, 12 Mar 2025 at 09:14, vignesh C <vignesh21@gmail.com> wrote:
    >
    > The patch was not applying on top of HEAD because of recent commits,
    > here is a rebased version.
    
    I have moved this to the next CommitFest since it will not be
    committed in the current release. This also allows reviewers to focus
    on the remaining patches in the current CommitFest.
    
    Regards,
    Vignesh
    
    
    
    
  195. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-03-25T05:35:46Z

    On Wed, 12 Mar 2025 at 09:14, vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > The patch was not applying on top of HEAD because of recent commits,
    > here is a rebased version.
    
    The patch was not applying on top of HEAD because of recent commits,
    here is a rebased version.
    
    Regards,
    Vignesh
    
  196. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-13T23:01:36Z

    Hi Vignesh,
    
    Here are some review comments for patch v20250325-0001.
    
    ======
    src/test/regress/expected/sequence.out
    
    1.
    +SELECT last_value, log_cnt, is_called  FROM
    pg_sequence_state('sequence_test');
    + last_value | log_cnt | is_called
    +------------+---------+-----------
    +         99 |      32 | t
    +(1 row)
    +
    
    I think 32 may seem like a surprising value to anybody reading these
    results. Perhaps it will help if there can be a comment for this .sql
    test to explain why this is the expected value.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  197. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-14T02:56:01Z

    Hi Vignesh,
    
    Some review comments for patch v20250325-0002
    
    ======
    Commit message
    
    1.
    Furthermore, enhancements to psql commands (\d and \dRp) now allow for better
    display of publications containing specific sequences or sequences included
    in a publication.
    
    ~
    
    That doesn't seem as clear as it might be. Also, IIUC the "sequences
    included in a publication" is not actually implemented yet -- there is
    only the "all sequences" flag.
    
    SUGGESTION
    Furthermore, enhancements to psql commands now display which
    publications contain the specified sequence (\d command), and if a
    specified publication includes all sequences (\dRp command)
    
    ======
    doc/src/sgml/ref/create_publication.sgml
    
    2.
       <para>
        To add a table to a publication, the invoking user must have ownership
    -   rights on the table.  The <command>FOR ALL TABLES</command> and
    -   <command>FOR TABLES IN SCHEMA</command> clauses require the invoking
    +   rights on the table.  The <command>FOR TABLES IN SCHEMA</command>,
    +   <command>FOR ALL TABLES</command> and
    +   <command>FOR ALL SEQUENCES</command> clauses require the invoking
        user to be a superuser.
    
    IMO these should all be using <literal> SGML markup same as elsewhere
    on this page, not <command> markup.
    
    ======
    src/backend/commands/publicationcmds.c
    
    3.
    if (!superuser_arg(newOwnerId))
    {
      if (form->puballtables)
        ereport(ERROR,
                errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                errmsg("permission denied to change owner of publication \"%s\"",
                       NameStr(form->pubname)),
                errhint("The owner of a FOR ALL TABLES publication must be
    a superuser."));
      if (form->puballsequences)
        ereport(ERROR,
                errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                errmsg("permission denied to change owner of publication \"%s\"",
                       NameStr(form->pubname)),
                errhint("The owner of a FOR ALL SEQUENCES publication must
    be a superuser."));
      if (is_schema_publication(form->oid))
        ereport(ERROR,
                errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                errmsg("permission denied to change owner of publication \"%s\"",
                       NameStr(form->pubname)),
                errhint("The owner of a FOR TABLES IN SCHEMA publication
    must be a superuser."));
    }
    
    I wondered if there's too much duplicated code here. Maybe it's better
    to share a common ereport?
    
    SUGGESTION
    
    if (!superuser_arg(newOwnerId))
    {
      char *hint_msg = NULL;
    
      if (form->puballtables)
        hint_msg = _("The owner of a FOR ALL TABLES publication must be a
    superuser.");
      else if (form->puballsequences)
        hint_msg = _("The owner of a FOR ALL SEQUENCES publication must be
    a superuser.");
      else if (is_schema_publication(form->oid))
        hint_msg = _("The owner of a FOR TABLES IN SCHEMA publication must
    be a superuser.");
      if (hint_msg)
        ereport(ERROR,
                errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                errmsg("permission denied to change owner of publication \"%s\"",
                       NameStr(form->pubname)),
                errhint(hint_msg));
    }
    
    ======
    src/bin/psql/describe.c
    
    describeOneTableDetails:
    
    4.
    + res = PSQLexec(buf.data);
    + if (!res)
    + goto error_return;
    +
    + numrows = PQntuples(res);
    +
    
    Isn't this same code already done a few lines above in the same
    function? Maybe I misread something.
    
    ======
    src/test/regress/sql/publication.sql
    
    5.
    +-- check that describe sequence lists all publications the sequence belongs to
    
    Might be clearer to say:  "lists both" instead of "lists all"
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  198. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-14T04:50:59Z

    Hi Vignesh,
    
    FYI, the patch v20250325-0004 failed to apply (atop 0001,0002,0002)
    due to recent master changes.
    
    Checking patch src/backend/commands/sequence.c...
    error: while searching for:
    (long long) minv, (long long) maxv)));
    
    /* Set the currval() state only if iscalled = true */
    if (iscalled)
    {
    elm->last = next; /* last returned number */
    elm->last_valid = true;
    
    error: patch failed: src/backend/commands/sequence.c:994
    error: src/backend/commands/sequence.c: patch does not apply
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  199. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-04-14T09:34:57Z

    On Mon, 14 Apr 2025 at 08:26, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Some review comments for patch v20250325-0002
    >
    > ======
    > Commit message
    >
    > 1.
    > Furthermore, enhancements to psql commands (\d and \dRp) now allow for better
    > display of publications containing specific sequences or sequences included
    > in a publication.
    >
    > ~
    >
    > That doesn't seem as clear as it might be. Also, IIUC the "sequences
    > included in a publication" is not actually implemented yet -- there is
    > only the "all sequences" flag.
    >
    > SUGGESTION
    > Furthermore, enhancements to psql commands now display which
    > publications contain the specified sequence (\d command), and if a
    > specified publication includes all sequences (\dRp command)
    
    Modified
    
    > ======
    > doc/src/sgml/ref/create_publication.sgml
    >
    > 2.
    >    <para>
    >     To add a table to a publication, the invoking user must have ownership
    > -   rights on the table.  The <command>FOR ALL TABLES</command> and
    > -   <command>FOR TABLES IN SCHEMA</command> clauses require the invoking
    > +   rights on the table.  The <command>FOR TABLES IN SCHEMA</command>,
    > +   <command>FOR ALL TABLES</command> and
    > +   <command>FOR ALL SEQUENCES</command> clauses require the invoking
    >     user to be a superuser.
    >
    > IMO these should all be using <literal> SGML markup same as elsewhere
    > on this page, not <command> markup.
    
    Modified
    
    > ======
    > src/backend/commands/publicationcmds.c
    >
    > 3.
    > if (!superuser_arg(newOwnerId))
    > {
    >   if (form->puballtables)
    >     ereport(ERROR,
    >             errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    >             errmsg("permission denied to change owner of publication \"%s\"",
    >                    NameStr(form->pubname)),
    >             errhint("The owner of a FOR ALL TABLES publication must be
    > a superuser."));
    >   if (form->puballsequences)
    >     ereport(ERROR,
    >             errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    >             errmsg("permission denied to change owner of publication \"%s\"",
    >                    NameStr(form->pubname)),
    >             errhint("The owner of a FOR ALL SEQUENCES publication must
    > be a superuser."));
    >   if (is_schema_publication(form->oid))
    >     ereport(ERROR,
    >             errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    >             errmsg("permission denied to change owner of publication \"%s\"",
    >                    NameStr(form->pubname)),
    >             errhint("The owner of a FOR TABLES IN SCHEMA publication
    > must be a superuser."));
    > }
    >
    > I wondered if there's too much duplicated code here. Maybe it's better
    > to share a common ereport?
    >
    > SUGGESTION
    >
    > if (!superuser_arg(newOwnerId))
    > {
    >   char *hint_msg = NULL;
    >
    >   if (form->puballtables)
    >     hint_msg = _("The owner of a FOR ALL TABLES publication must be a
    > superuser.");
    >   else if (form->puballsequences)
    >     hint_msg = _("The owner of a FOR ALL SEQUENCES publication must be
    > a superuser.");
    >   else if (is_schema_publication(form->oid))
    >     hint_msg = _("The owner of a FOR TABLES IN SCHEMA publication must
    > be a superuser.");
    >   if (hint_msg)
    >     ereport(ERROR,
    >             errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    >             errmsg("permission denied to change owner of publication \"%s\"",
    >                    NameStr(form->pubname)),
    >             errhint(hint_msg));
    > }
    
    I felt the existing code is ok in this case. It will be easier to
    review if the error hint is along with ereport in this case.
    
    > ======
    > src/bin/psql/describe.c
    >
    > describeOneTableDetails:
    >
    > 4.
    > + res = PSQLexec(buf.data);
    > + if (!res)
    > + goto error_return;
    > +
    > + numrows = PQntuples(res);
    > +
    >
    > Isn't this same code already done a few lines above in the same
    > function? Maybe I misread something.
    
    Modified
    
    > ======
    > src/test/regress/sql/publication.sql
    >
    > 5.
    > +-- check that describe sequence lists all publications the sequence belongs to
    >
    > Might be clearer to say:  "lists both" instead of "lists all"
    
    Modified
    
    Regarding comment at [1]. On further thinking I have removed that test
    as one test is enough for that change, so the comment handling is no
    more required.
    Regarding comment at [2]. The attached patch has the rebased changes too.
    
    The attached v20250414 version patch has the changes for the same.
    
    [1] - https://www.postgresql.org/message-id/CAHut%2BPsgZkEegDzhJ2%3DDwDkrks6g6aQ6LX1-M%2BXBBt4PP-MX3g%40mail.gmail.com
    [2] - https://www.postgresql.org/message-id/CAHut%2BPv5XMnX%2BQSSDhL5eqXV%3Dkp22jyYOgFx_u7kSMhwvktvrg%40mail.gmail.com
    
    Regards,
    Vignesh
    
  200. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-15T06:33:04Z

    Hi Vignesh,
    
    Some review comments for v20250525-0004.
    
    ======
    Commit message
    
    1.
    A new sequencesync worker is launched as needed to synchronize sequences.
    It does the following:
        a) Retrieves remote values of sequences with pg_sequence_state() INIT.
        b) Log a warning if the sequence parameters differ between the
    publisher and subscriber.
        c) Sets the local sequence values accordingly.
        d) Updates the local sequence state to READY.
        e) Repeat until all done; Commits synchronized sequences in batches of 100
    
    ~
    
    /Log a warning/Logs a warning/
    /Repeat until all done/Repeats until all done/
    
    ~~~
    
    2.
    1) CREATE SUBSCRIPTION
        - (PG17 command syntax is unchanged)
        - The subscriber retrieves sequences associated with publications.
        - Published sequences are added to pg_subscription_rel with INIT state.
        - Initiates the sequencesync worker (see above) to synchronize all
          sequences.
    
    ~
    
    2a.
    Since PG18 is frozen now I think you can say "PG18 command syntax is unchanged"
    (replace same elsewhere in this commit message)
    
    ~
    
    2b.
    /Initiates/Initiate/
    (replace same elsewhere in this commit message)
    
    ======
    src/backend/catalog/pg_publication.c
    
    pg_get_publication_sequences:
    
    3.
    +Datum
    +pg_get_publication_sequences(PG_FUNCTION_ARGS)
    +{
    + FuncCallContext *funcctx;
    + char    *pubname = text_to_cstring(PG_GETARG_TEXT_PP(0));
    + Publication *publication;
    + List    *sequences = NIL;
    +
    + /* stuff done only on the first call of the function */
    + if (SRF_IS_FIRSTCALL())
    + {
    
    The 'pubname' and 'publication' variables can be declared later,
    within the SRF_IS_FIRSTCALL block.
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    CreateSubscription:
    
    4.
    + /*
    + * XXX: If the subscription is for a sequence-only publication, creating
    + * this origin is unnecessary. It can be created later during the ALTER
    + * SUBSCRIPTION ... REFRESH command, if the publication is updated to
    + * include tables or tables in schemas.
    + */
    
    Since it already says "to include tables", I didn't think you needed
    to say "tables in schemas".
    
    ~~~
    
    5.
    + *
    + * XXX: If the subscription is for a sequence-only publication,
    + * creating this slot is unnecessary. It can be created later
    + * during the ALTER SUBSCRIPTION ... REFRESH PUBLICATION or ALTER
    + * SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES command, if the
    + * publication is updated to include tables or tables in schema.
      */
    
    (same comment as above #4).
    
    I thought maybe it is redundant to say "or tables in schema".
    
    ~~~
    
    AlterSubscription_refresh:
    
    6.
    +#ifdef USE_ASSERT_CHECKING
    + if (resync_all_sequences)
    + Assert(copy_data && !refresh_tables && refresh_sequences);
    +#endif
    +
    
    Maybe this can have a comment like /* Sanity checks for parameter values */
    
    ~~~
    
    7.
    + sub_remove_rels[remove_rel_len].relid = relid;
    + sub_remove_rels[remove_rel_len++].state = state;
    
      /*
    - * For READY state, we would have already dropped the
    - * tablesync origin.
    + * A single sequencesync worker synchronizes all sequences, so
    + * only stop workers when relation kind is not sequence.
      */
    - if (state != SUBREL_STATE_READY)
    + if (relkind != RELKIND_SEQUENCE)
    
    Should those assignments...:
    sub_remove_rels[remove_rel_len].relid = relid;
    sub_remove_rels[remove_rel_len++].state = state;
    
    ...be done only inside the "if (relkind != RELKIND_SEQUENCE)". It
    seems like they'll be skipped anyway in subsequent code -- see "if
    (get_rel_relkind(sub_remove_rels[off].relid) == RELKIND_SEQUENCE)".
    Perhaps if these assignments are moved, then the subsequent skipping
    code is also not needed anymore?
    
    ======
    src/backend/replication/logical/launcher.c
    
    logicalrep_worker_launch:
    
    8.
    + case WORKERTYPE_SEQUENCESYNC:
    + snprintf(bgw.bgw_function_name, BGW_MAXLEN, "SequenceSyncWorkerMain");
    + snprintf(bgw.bgw_name, BGW_MAXLEN,
    + "logical replication sequencesync worker for subscription %u",
    + subid);
    + snprintf(bgw.bgw_type, BGW_MAXLEN, "logical replication sequencesync worker");
    + break;
    +
    
    Previously all these cases were in alphabetical order. Maybe you can
    move this case to keep it that way.
    
    ~~~
    
    pg_stat_get_subscription:
    
    9.
      case WORKERTYPE_TABLESYNC:
      values[9] = CStringGetTextDatum("table synchronization");
      break;
    + case WORKERTYPE_SEQUENCESYNC:
    + values[9] = CStringGetTextDatum("sequence synchronization");
    + break;
    
    Previously all these cases were in alphabetical order. Maybe you can
    move this case to keep it that way.
    
    ======
    .../replication/logical/sequencesync.c
    
    ProcessSyncingSequencesForApply:
    
    10.
    + * To prevent starting the sequencesync worker at a high frequency after a
    + * failure, we store its last failure time. We start the sequencesync worker
    + * again after waiting at least wal_retrieve_retry_interval.
    
    I felt this comment might be better inside the function where it is
    doing the TimestampDifferenceExceeds check.
    
    ~~~
    
    10.
    + if (!started_tx)
    + {
    + StartTransactionCommand();
    + started_tx = true;
    + }
    +
    + Assert(get_rel_relkind(rstate->relid) == RELKIND_SEQUENCE);
    
    Maybe the Assert should come 1st before the tx stuff?
    
    ~~~
    
    11.
    + /*
    + * If there are free sync worker slot(s), start a new sequencesync
    + * worker, and break from the loop.
    + */
    
    Why plural? Can't you just say.
    
    SUGGESTION:
    If there is a free sync worker slot, start a new sequencesync worker,
    and break from the loop.
    
    ~~~
    
    fetch_remote_sequence_data:
    
    12.
    + Oid tableRow[REMOTE_SEQ_COL_COUNT] = {INT8OID, INT8OID, BOOLOID,
    + LSNOID, OIDOID, INT8OID, INT8OID, INT8OID, INT8OID, BOOLOID};
    
    Is 'tableRow' a good name for this? Calling it 'seqRow' might be better.
    
    ~~~
    
    13.
    + seq_params_match = seqform->seqtypid == seqtypid &&
    + seqform->seqmin == seqmin && seqform->seqmax == seqmax &&
    + seqform->seqcycle == seqcycle &&
    + seqform->seqstart == seqstart &&
    + seqform->seqincrement == seqincrement;
    
    By the time the WARNING for this mismatch gets logged, the knowledge
    of *what* differed seems lost. Maybe it is not possible, but I
    wondered if it would make the warning much more useful if you could
    somehow also log attribute values. That will help the user understand
    what caused the clash in the first place. Otherwise they will have to
    go to the trouble to try to figure it out for themselves.
    
    ~~~
    
    copy_sequence:
    
    14.
    +/*
    + * Copy existing data of a sequence from publisher.
    
    /from/from the/
    
    ~~~
    
    15.
    + Oid tableRow[] = {OIDOID, CHAROID};
    
    Should this be 'seqRow' or 'relRow'?
    
    ~~~
    
    16.
    + *sequence_mismatch = !fetch_remote_sequence_data(conn, relid, remoteid,
    + nspname, relname,
    + &seq_log_cnt, &seq_is_called,
    + &seq_page_lsn, &seq_last_value);
    +
    + /* Update the sequence only if the parameters are identical. */
    + if (*sequence_mismatch == false)
    + SetSequence(RelationGetRelid(rel), seq_last_value, seq_is_called,
    + seq_log_cnt);
    +
    + /* Return the LSN when the sequence state was set. */
    + return seq_page_lsn;
    
    16a.
    Is that a bug in the code? AFAICT the fetch_remote_sequence_data is
    going to overwrite the new 'seq_page_lsn' even if some mismatch is
    detected. Is that intentional?
    
    ~
    
    16b.
    Why not say "if (!*sequence_mismatch)"
    
    ~
    
    16c.
    Since it is not 100% clear from this code what will be the value of
    seq_page_lsn when if there was a mismatch, maybe you should have a
    more explicit return here:
    
    SUGGESTION
    return *sequence_mismatch ? InvalidXLogRecPtr : seq_page_lsn;
    
    ~~~
    
    append_mismatched_sequences:
    
    17.
    +/*
    + * append_mismatched_sequences
    + *
    + * Appends details of sequences that have discrepancies between the publisher
    + * and subscriber to the mismatched_seqs string.
    + */
    
    Hmm. It would be good if it did include sequence details, but I think
    for now there are no real "details of sequences" here. just the
    schemaname and seqname.
    
    ~~~
    
    LogicalRepSyncSequences:
    
    18.
    +/*
    + * Synchronizing each sequence individually incurs overhead from starting
    + * and committing a transaction repeatedly. Additionally, we want to avoid
    + * keeping transactions open for extended periods by setting excessively
    + * high values.
    + */
    +#define MAX_SEQUENCES_SYNC_PER_BATCH 100
    
    Just saying "by setting excessively high values." doesn't really have
    any context. high values of what? You have to guess what it means.
    
    I think it is more like below.
    
    SUGGESTION
    We batch synchronize multiple sequences per transaction, because the
    alternative of synchronizing each sequence individually incurs
    overhead of starting and committing transactions repeatedly. On the
    other hand, we want to avoid keeping this batch transaction open for
    extended periods so it is currently limited to 100 sequences per
    batch.
    
    ~~~
    
    19.
    + /*
    + * In case sequence copy fails, throw a warning for the sequences that
    + * did not match before exiting.
    + */
    + PG_TRY();
    + {
    + sequence_lsn = copy_sequence(LogRepWorkerWalRcvConn, sequence_rel,
    + &sequence_mismatch);
    + }
    + PG_CATCH();
    + {
    + if (sequence_mismatch)
    + append_mismatched_sequences(mismatched_seqs, sequence_rel);
    +
    + report_mismatched_sequences(mismatched_seqs);
    + PG_RE_THROW();
    + }
    
    If we got to the CATCH then it means some ERROR happened, but at that
    point I really don't think  sequence_mismatch is likely to be set as
    true. Maybe it is you just being extra careful, "just in case" ?
    
    ~~~
    
    20.
    + if (mismatched_seqs->len)
    + sequence_sync_error = true;
    +
    + report_mismatched_sequences(mismatched_seqs);
    
    I think you can put that call to report_mismatched_sequences under the
    same condition, because if there are no mismatches then there will be
    nothing to report anyhow.
    
    ~~~
    
    21.
    + /*
    + * Sequence synchronization failed due to a parameter mismatch. Setting
    + * the failure time to prevent repeated initiation of the sequencesync
    + * worker.
    + */
    
    /Setting/Set/
    
    /to prevent repeated initiation/to prevent immediate initiation/ (??)
    
    ======
    src/backend/replication/logical/syncutils.c
    
    FetchRelationStates:
    
    22.
    + /*
    + * This is declared as static, since the same value can be used until the
    + * system table is invalidated.
    + */
      static bool has_subtables = false;
    /This/has_subtables/
    
    ======
    src/backend/replication/logical/tablesync.c
    
    ProcessSyncingTablesForApply:
    
    23.
    + if (!started_tx)
    + {
    + StartTransactionCommand();
    + started_tx = true;
    + }
    +
    + Assert(get_rel_relkind(rstate->relid) != RELKIND_SEQUENCE);
    +
    
    Should this Assert come before the other tx code?
    
    ~~~
    
    AllTablesyncsReady:
    
    24.
    + bool has_tables = false;
    
      /* We need up-to-date sync state info for subscription tables here. */
    - has_subrels = FetchRelationStates(&started_tx);
    -
    - if (started_tx)
    - {
    - CommitTransactionCommand();
    - pgstat_report_stat(true);
    - }
    + has_tables = FetchRelationStates();
    
    Don't need to assign has_tables to false if the value will be
    immediately overwritten anyhow.
    
    ======
    src/bin/pg_dump/pg_dump.c
    
    getSubscriptionRelations:
    
    25.
    -getSubscriptionTables(Archive *fout)
    +getSubscriptionRelations(Archive *fout)
    
    Although you changed the function command and the function name for ,
    there is still code within that function referring to tables. Should
    that also be changed to relations?
    
    ======
    src/include/commands/sequence.h
    
    26.
    +#define SEQ_LOG_CNT_INVALID 0
    
    Zero seemed like a curious value to use as the "invalid" count. I was
    wondering would it be better to define this as -1, but then in the
    SetSequence function do some explicit code like below:
    
    seq->log_cnt = log_cnt == SEQ_LOG_CNT_INVALID ? 0 : log_cnt;
    
    ======
    src/test/subscription/t/036_sequences.pl
    
    27.
    +# Check the initial data on subscriber
    +my $result = $node_subscriber->safe_psql(
    + 'postgres', qq(
    + SELECT last_value, log_cnt, is_called FROM regress_s1;
    +));
    +is($result, '100|32|t', 'initial test data replicated');
    
    I think this deserves some explanatory comment about the magic number
    32? But, it may be better to have a general comment at the top of this
    TAP test to explain other magic numbers like 31 etc...
    
    ~~~
    
    28.
    +# Check - existing sequence is not synced
    +$result = $node_subscriber->safe_psql(
    + 'postgres', qq(
    + SELECT last_value, log_cnt, is_called FROM regress_s1;
    +));
    +is($result, '100|32|t',
    + 'REFRESH PUBLICATION does not sync existing sequence');
    
    This test would be clearer if you also checked those same sequence
    values at the publisher side, to show they are different. Don't need
    to do it every time, but maybe just this first time would be good.
    
    ~~~
    
    29.
    +# Check - newly published sequence values are not updated
    +$result = $node_subscriber->safe_psql(
    + 'postgres', qq(
    + SELECT last_value, log_cnt, is_called FROM regress_s4;
    +));
    +is($result, '1|0|f',
    + 'REFRESH PUBLICATION will sync newly published sequence');
    +
    
    (This is the copy_data=false test)
    
    29a.
    Maybe it is good here also to show the sequence value at the publisher
    to see if it is different.
    
    ~
    
    29b.
    The message 'REFRESH PUBLICATION will sync newly published sequence'
    seems wrong because the values are NOT synced when copy_data=false
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  201. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-16T01:38:39Z

    Hi Vignesh,
    
    Some review comments for patch v20250325-0005 (docs).
    
    ======
    doc/src/sgml/catalogs.sgml
    
    (52.55. pg_subscription_rel)
    
    1.
    State code: i = initialize, d = data is being copied, f = finished
    table copy, s = synchronized, r = ready (normal replication)
    
    ~
    
    This is not part of the patch, but AFAIK not all of those states are
    relevant if the srrelid was a SEQUENCE relation. Should there be 2
    sets of states given here for what is possible for tables/sequences?
    
    ======
    doc/src/sgml/config.sgml
    
    (19.6.4. Subscribers)
    
    2.
            <para>
             In logical replication, this parameter also limits how often a failing
    -        replication apply worker or table synchronization worker will be
    -        respawned.
    +        replication apply worker or table synchronization worker or sequence
    +        synchronization worker will be respawned.
            </para>
    
    Does it though? I thought /often/quickly/ because if there is some
    ERROR the respawning may occur again and again forever, so you are not
    really limiting how often it occurs, only the *rate* at which the
    respawning happens.
    
    ======
    doc/src/sgml/logical-replication.sgml
    
    (29.1 Publication)
    
    3.
        Publications may currently only contain tables and all tables in schema.
        Objects must be added explicitly, except when a publication is created for
    -   <literal>ALL TABLES</literal>.
    +   <literal>ALL TABLES</literal>. Publications can include sequences as well,
    +   but their behavior differs from that of tables or groups of tables. Unlike
    +   tables, sequences allow users to synchronize their current state at any
    +   given time. For more information, refer to
    +   <xref linkend="logical-replication-sequences"/>.
       </para>
    
    This doesn't really make sense. The change seems too obviously just
    tacked onto the end of the existing documentation. e.g It is strange
    saying "Publications may currently only contain tables and all tables
    in schema." and then later saying Oh, BTW "Publications can include
    sequences as well". I think the whole paragraph may need some
    reworking.
    
    The preceding para on this page also still says "A publication is a
    set of changes generated from a table or a group of tables" which also
    failed to mention sequences.
    
    OTOH, I think it would get too confusing to mush everything together,
    so after saying  publish tables and sequences, then I think there
    should be one paragraph that just talks about publishing tables,
    followed by another paragraph that just talks about publishing
    sequences. Probably this should mention ALL SEQUENCES too since it
    already mentioned ALL TABLES.
    
    ~~~
    
    (29.6. Replicating Sequences)
    
    4.
    +  <para>
    +   To replicate sequences from a publisher to a subscriber, first publish the
    +   sequence using <link
    linkend="sql-createpublication-params-for-all-sequences">
    +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link>.
    +  </para>
    
    /first publish the sequence/first publish them/
    
    ~~~
    
    5.
    +  <para>
    +   A new <firstterm>sequence synchronization worker</firstterm> will be started
    +   to synchronize the sequences after executing any of the above subscriber
    +   commands, and will exit once the sequences are synchronized.
    +  </para>
    
    IMO the name of the worker makes it obvious what it does so I think
    you can remove the redundant words "to synchronize the sequences" from
    this sentence.
    
    ~~~
    
    (29.7.1. Sequence Definition Mismatches)
    
    6.
    +   <para>
    +    To resolve this, use
    +    <link linkend="sql-altersequence"><command>ALTER SEQUENCE</command></link>
    +    to align the subscriber's sequence parameters with those of the publisher.
    +    Subsequently, execute <link
    linkend="sql-altersubscription-params-refresh-publication-sequences">
    +    <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES</command></link>.
    +   </para>
    
    /Subsequently,/Then,/
    
    ~~~
    
    (29.6.3. Examples)
    
    7.
    +   <para>
    +    Create some test sequences on the publisher.
    
    This whole section is just examples, so I don't think you need to call
    them "test" sequences. Just say "Create some sequences on the
    publisher.".
    
    ~~~
    
    (29.9. Restrictions)
    
    8.
         <para>
    -     Sequence data is not replicated.  The data in serial or identity columns
    -     backed by sequences will of course be replicated as part of the table,
    -     but the sequence itself would still show the start value on the
    -     subscriber.  If the subscriber is used as a read-only database, then this
    -     should typically not be a problem.  If, however, some kind of switchover
    -     or failover to the subscriber database is intended, then the sequences
    -     would need to be updated to the latest values, either by copying the
    -     current data from the publisher (perhaps
    -     using <command>pg_dump</command>) or by determining a sufficiently high
    -     value from the tables themselves.
    +     Incremental sequence changes are not replicated.  The data in serial or
    +     identity columns backed by sequences will of course be replicated as part
    +     of the table, but the sequence itself would still show the start value on
    +     the subscriber.  If the subscriber is used as a read-only database, then
    +     this should typically not be a problem.  If, however, some kind of
    +     switchover or failover to the subscriber database is intended, then the
    +     sequences would need to be updated to the latest values, either
    by executing
    +     <link linkend="sql-altersubscription-params-refresh-publication-sequences">
    +     <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES</command></link>
    +     or by copying the current data from the publisher (perhaps using
    +     <command>pg_dump</command>) or by determining a sufficiently high value
    +     from the tables themselves.
         </para>
    
    This doesn't seem strictly correct to say "but the sequence itself
    would still show the start value on the subscriber". AFAIK,
    synchronization also happens on the CREATE SUBSCRIPTION command when
    copy_data=true, so if any sequences had been published (FOR ALL
    SEQUENCES) then the subscriber sequence would get the up-to-date
    current values (not the "start value"), right?
    
    ~~~
    
    (29.13.2. Subscribers)
    
    9.
        <para>
         <link linkend="guc-max-sync-workers-per-subscription"><varname>max_sync_workers_per_subscription</varname></link>
          controls the amount of parallelism of the initial data copy during the
    -     subscription initialization or when new tables are added.
    +     subscription initialization or when new tables or sequences are added.
        </para>
    
    This seems kind of misleading because there is no "amount of
    parallelism" for sequences since there is never more than one sequence
    sync worker. Maybe there is a more accurate way to word this.
    
    SUGGESTION (maybe like this?)
    max_sync_workers_per_subscription controls how many tables can be
    synchronized in parallel during subscription initialization or when
    new tables are added. One additional worker is also needed for
    sequence synchronization.
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    (ALTER SUBSCRIPTION REFRESH PUBLICATION / copy_data)
    
    10.
    +         <para>
    +          See <xref linkend="sequence-definition-mismatches"/> for
    recommendations on how
    +          to handle any warnings about differences in the sequence definition
    +          between the publisher and the subscriber, which might occur when
    +          <literal>copy_data = true</literal>.
    +         </para>
    
    /any warnings about differences in the sequence definition between/any
    warnings about sequence definition differences between/
    
    ~~~
    
    (ALTER SUBSCRIPTION REFRESH PUBLICATION SEQUENCES)
    
    11.
    +     <para>
    +      See <xref linkend="sequence-definition-mismatches"/> for
    +      recommendations on how to handle any warnings about differences in the
    +      sequence definition between the publisher and the subscriber.
    +     </para>
    
    Ditto my previous review comment #10.
    
    ======
    doc/src/sgml/ref/create_subscription.sgml
    
    (CREATE SUBSCRIPTION / copy_data)
    
    12.
    +         <para>
    +          See <xref linkend="sequence-definition-mismatches"/>
    +          for recommendations on how to handle any warnings about
    differences in
    +          the sequence definition between the publisher and the subscriber,
    +          which might occur when <literal>copy_data = true</literal>.
    +         </para>
    
    Ditto my previous review comment #10.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  202. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-04-16T13:29:19Z

    On Tue, 15 Apr 2025 at 12:03, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Some review comments for v20250525-0004.
    >
    > ======
    > Commit message
    > ProcessSyncingSequencesForApply:
    >
    > 10.
    > + if (!started_tx)
    > + {
    > + StartTransactionCommand();
    > + started_tx = true;
    > + }
    > +
    > + Assert(get_rel_relkind(rstate->relid) == RELKIND_SEQUENCE);
    >
    > Maybe the Assert should come 1st before the tx stuff?
    
    The existing is correct, get_rel_kind call requires transaction to be started.
    >
    > 13.
    > + seq_params_match = seqform->seqtypid == seqtypid &&
    > + seqform->seqmin == seqmin && seqform->seqmax == seqmax &&
    > + seqform->seqcycle == seqcycle &&
    > + seqform->seqstart == seqstart &&
    > + seqform->seqincrement == seqincrement;
    >
    > By the time the WARNING for this mismatch gets logged, the knowledge
    > of *what* differed seems lost. Maybe it is not possible, but I
    > wondered if it would make the warning much more useful if you could
    > somehow also log attribute values. That will help the user understand
    > what caused the clash in the first place. Otherwise they will have to
    > go to the trouble to try to figure it out for themselves.
    
    I felt it might be ok for users to get this using the sequence name.
    >
    > 16.
    > + *sequence_mismatch = !fetch_remote_sequence_data(conn, relid, remoteid,
    > + nspname, relname,
    > + &seq_log_cnt, &seq_is_called,
    > + &seq_page_lsn, &seq_last_value);
    > +
    > + /* Update the sequence only if the parameters are identical. */
    > + if (*sequence_mismatch == false)
    > + SetSequence(RelationGetRelid(rel), seq_last_value, seq_is_called,
    > + seq_log_cnt);
    > +
    > + /* Return the LSN when the sequence state was set. */
    > + return seq_page_lsn;
    >
    > 16a.
    > Is that a bug in the code? AFAICT the fetch_remote_sequence_data is
    > going to overwrite the new 'seq_page_lsn' even if some mismatch is
    > detected. Is that intentional?
    
    In the caller we set the sequence lsn only if sequence_mismatch is
    false, so there is no issue.
    
    > 19.
    > + /*
    > + * In case sequence copy fails, throw a warning for the sequences that
    > + * did not match before exiting.
    > + */
    > + PG_TRY();
    > + {
    > + sequence_lsn = copy_sequence(LogRepWorkerWalRcvConn, sequence_rel,
    > + &sequence_mismatch);
    > + }
    > + PG_CATCH();
    > + {
    > + if (sequence_mismatch)
    > + append_mismatched_sequences(mismatched_seqs, sequence_rel);
    > +
    > + report_mismatched_sequences(mismatched_seqs);
    > + PG_RE_THROW();
    > + }
    >
    > If we got to the CATCH then it means some ERROR happened, but at that
    > point I really don't think  sequence_mismatch is likely to be set as
    > true. Maybe it is you just being extra careful, "just in case" ?
    
    In this function we copy the sequences_not_synced sequences one by
    one, while copying the sequence if there is an error like sequence
    type or min or max etc don't match , sequence_mismatch will be set.
    Later while copying another sequence if an exception is raised and we
    reach catch block, we report an error this case.
    
    >
    > 21.
    > + /*
    > + * Sequence synchronization failed due to a parameter mismatch. Setting
    > + * the failure time to prevent repeated initiation of the sequencesync
    > + * worker.
    > + */
    >
    > /to prevent repeated initiation/to prevent immediate initiation/ (??)
    
    I felt repeated is correct here as we don't want to repeatedly start
    the sequence sync worker after every failure.
    
    > 23.
    > + if (!started_tx)
    > + {
    > + StartTransactionCommand();
    > + started_tx = true;
    > + }
    > +
    > + Assert(get_rel_relkind(rstate->relid) != RELKIND_SEQUENCE);
    > +
    >
    > Should this Assert come before the other tx code?
    
    The existing is correct, get_rel_kind call requires a transaction to be started.
    
    > 25.
    > -getSubscriptionTables(Archive *fout)
    > +getSubscriptionRelations(Archive *fout)
    >
    > Although you changed the function command and the function name for ,
    > there is still code within that function referring to tables. Should
    > that also be changed to relations?
    
    You are talking about the error message right, I have changed that.
    
    > ======
    > src/include/commands/sequence.h
    >
    > 26.
    > +#define SEQ_LOG_CNT_INVALID 0
    >
    > Zero seemed like a curious value to use as the "invalid" count. I was
    > wondering would it be better to define this as -1, but then in the
    > SetSequence function do some explicit code like below:
    >
    > seq->log_cnt = log_cnt == SEQ_LOG_CNT_INVALID ? 0 : log_cnt;
    
    I felt using 0 in this case is ok.
    
    > ======
    > src/test/subscription/t/036_sequences.pl
    >
    > 27.
    > +# Check the initial data on subscriber
    > +my $result = $node_subscriber->safe_psql(
    > + 'postgres', qq(
    > + SELECT last_value, log_cnt, is_called FROM regress_s1;
    > +));
    > +is($result, '100|32|t', 'initial test data replicated');
    >
    > I think this deserves some explanatory comment about the magic number
    > 32? But, it may be better to have a general comment at the top of this
    > TAP test to explain other magic numbers like 31 etc...
    
    log_cnt is prefetched sequence values, it is not a special magic
    value. I felt no need to add any comment for this.
    
    Rest of the comments are fixed.
    
    Regarding the comments from [1].
    1. State code: i = initialize, d = data is being copied, f = finished
    table copy, s = synchronized, r = ready (normal replication)
    ~
    This is not part of the patch, but AFAIK not all of those states are
    relevant if the srrelid was a SEQUENCE relation. Should there be 2
    sets of states given here for what is possible for tables/sequences?
    
    I have updated the states which are not applicable for sequences in
    the same page.
    
    3.     Publications may currently only contain tables and all tables in schema.
        Objects must be added explicitly, except when a publication is created for
    -   <literal>ALL TABLES</literal>.
    +   <literal>ALL TABLES</literal>. Publications can include sequences as well,
    +   but their behavior differs from that of tables or groups of tables. Unlike
    +   tables, sequences allow users to synchronize their current state at any
    +   given time. For more information, refer to
    +   <xref linkend="logical-replication-sequences"/>.
       </para>
    
    This doesn't really make sense. The change seems too obviously just
    tacked onto the end of the existing documentation. e.g It is strange
    saying "Publications may currently only contain tables and all tables
    in schema." and then later saying Oh, BTW "Publications can include
    sequences as well". I think the whole paragraph may need some
    reworking.
    
    The preceding para on this page also still says "A publication is a
    set of changes generated from a table or a group of tables" which also
    failed to mention sequences.
    
    OTOH, I think it would get too confusing to mush everything together,
    so after saying  publish tables and sequences, then I think there
    should be one paragraph that just talks about publishing tables,
    followed by another paragraph that just talks about publishing
    sequences. Probably this should mention ALL SEQUENCES too since it
    already mentioned ALL TABLES.
    
    I did not create a separate paragraph for tables/sequences as there is
    a separate section for sequence with the reference.
    
    Rest of the comments are fixed. The attached v20250416 version patch
    has the changes for the same.
    
    [1] - https://www.postgresql.org/message-id/CAHut%2BPtc0gG%3D4j_BVqxHRGa%3DTKY_PsYu0RdsT6YuWPiNkSRhOQ%40mail.gmail.com
    
    Regards,
    Vignesh
    
  203. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-17T08:21:34Z

    Hi Vignesh,
    
    No comments for patch v20250416-0001
    No comments for patch v20250416-0002
    No comments for patch v20250416-0003
    
    Here are some comments for patch v20250416-0004
    
    ======
    src/backend/catalog/system_views.sql
    
    1.
    +CREATE VIEW pg_publication_sequences AS
    +    SELECT
    +        P.pubname AS pubname,
    +        N.nspname AS schemaname,
    +        C.relname AS sequencename
    +    FROM pg_publication P,
    +         LATERAL pg_get_publication_sequences(P.pubname) GPS,
    +         pg_class C JOIN pg_namespace N ON (N.oid = C.relnamespace)
    +    WHERE C.oid = GPS.relid;
    +
    
    Should we have some regression tests for this view?
    
    SUGGESTION
    test_pub=# CREATE SEQUENCE S1;
    test_pub=# CREATE SEQUENCE S2;
    test_pub=# CREATE PUBLICATION PUB1 FOR ALL SEQUENCES;
    test_pub=# SELECT * FROM pg_publication_sequences;
     pubname | schemaname | sequencename
    ---------+------------+--------------
     pub1    | public     | s1
     pub1    | public     | s2
    (2 rows)
    
    ======
    .../replication/logical/sequencesync.c
    
    copy_sequence:
    
    2.
    + res = walrcv_exec(conn, cmd.data,
    +   lengthof(seqRow), seqRow);
    
    Unnecessary wrapping.
    
    ~~~
    
    Vignesh 16/4 answered my previous review comment #16
    In the caller we set the sequence lsn only if sequence_mismatch is
    false, so there is no issue.
    
    PS REPLY 17/4. No, I don’t see that. I think
    fetch_remote_sequesnce_data is unconditionally assigning to the
    *page_lsn output parameter (aka seq_page_lsn). Anyway, it does not
    matter anymore since the return from copy_sequence function is now
    fixed.
    
    ~~~
    
    3.
    + /* Update the sequence only if the parameters are identical. */
    + if (!*sequence_mismatch)
    + SetSequence(RelationGetRelid(rel), seq_last_value, seq_is_called,
    + seq_log_cnt);
    +
    + /* Return the LSN when the sequence state was set. */
    + return *sequence_mismatch ? InvalidXLogRecPtr : seq_page_lsn;
    
    It might be simpler to have a single condition instead checking
    *sequence_mismatch twice.
    
    SUGGESTION
    /* Update the sequence only if the parameters are identical. */
    if (*sequence_mismatch)
      return InvalidXLogRecPtr;
    else
    {
      SetSequence(RelationGetRelid(rel), seq_last_value, seq_is_called,
                  seq_log_cnt);
      return seq_page_lsn;
    }
    
    ~~~
    
    LogicalRepSyncSequences:
    
    Vignesh 16/4 answered my previous comment #19:
    In this function we copy the sequences_not_synced sequences one by
    one, while copying the sequence if there is an error like sequence
    type or min or max etc don't match , sequence_mismatch will be set.
    Later while copying another sequence if an exception is raised and we
    reach catch block, we report an error this case.
    
    PS REPLY 17/4. I didn’t understand your explanation. I think anything
    that causes sequence_mismatch to be assigned true is just an internal
    logic state. It is not something that will be “thrown” and caught by
    the PG_CATCH. Therefore, I did not understand why the “if
    (sequence_mismatch)” needed to be within the PG_CATCH block.
    
    ~~~
    
    Vignesh 16/4 answered my previous review comment #21:
    I felt repeated is correct here as we don't want to repeatedly start
    the sequence sync worker after every failure.
    
    PS REPLY 17/4
    Hm. Is that correct? AFAIK we still will "repeatedly" start the
    sequence syn worker after a failure. I think the failure only *slows
    down* the respawn of the worker because it will use the
    TimestampDifferenceExceeds check if there had been a failure. That's
    why I suggested s/to prevent repeated initiation/to prevent immediate
    initiation/.
    
    ======
    src/bin/pg_dump/pg_dump.c
    
    getSubscriptionRelations:
    
    Vignesh 16/4 answered my previous review comment #25:
    You are talking about the error message right, I have changed that.
    
    PS REPLY 17/4
    Yes, the error message, but also I thought 'tblinfo' var and
    FindTableByOid function name should refer to relations instead of
    tables?
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  204. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-17T08:25:33Z

    Hi Vignesh,
    
    Some review comments for patch v20250416-0005 (docs)
    
    ======
    doc/src/sgml/catalogs.sgml
    
    (52.55. pg_subscription_rel)
    
    1.
           <para>
            State code:
            <literal>i</literal> = initialize,
    -       <literal>d</literal> = data is being copied,
    -       <literal>f</literal> = finished table copy,
    -       <literal>s</literal> = synchronized,
    +       <literal>d</literal> = data is being copied (not applicable
    for sequences),
    +       <literal>f</literal> = finished table copy (not applicable for
    sequences),
    +       <literal>s</literal> = synchronized (not applicable for sequences),
            <literal>r</literal> = ready (normal replication)
           </para></entry>
    
    Would this be simpler if you used separate paragraphs for tables and sequences?
    
    SUGGESTION
    State codes for tables: i = initialize, d = data is being copied, f =
    finished table copy, s = synchronized, d = data is being copied, f =
    finished table copy, s = synchronized, r = ready (normal replication)
    
    State codes for sequences: i = initialize, r = ready (normal replication)
    
    ======
    doc/src/sgml/logical-replication.sgml
    
    (29.1 Publication)
    
    2.
    -   generated from a table or a group of tables, and might also be described as
    -   a change set or replication set.  Each publication exists in only
    one database.
    +   generated from a table or a group of tables or current state of all
    +   sequences, and might also be described as a change set or replication set.
    +   Each publication exists in only one database.
    
    /or current state/or the current state/
    
    ~~~
    
    3.
       <para>
        Publications are different from schemas and do not affect how the table is
        accessed.  Each table can be added to multiple publications if needed.
    -   Publications may currently only contain tables and all tables in schema.
    +   Publications may currently only contain sequences or tables/all
    tables in schema.
        Objects must be added explicitly, except when a publication is created for
    -   <literal>ALL TABLES</literal>.
    +   <literal>ALL TABLES</literal> and <literal>ALL SEQUENCES</literal>.
    
    I don't think you need to say "/all tables in schema" because here we
    are talking about the *type* of objects that can be in the
    publication. OTOH, the FOR TABLES IN SCHEMA should be in the next
    sentence.
    
    SUGGESTION
    Publications may currently only contain tables or sequences. Objects
    must be added explicitly, except when a publication is created using
    FOR TABLES IN SCHEMA, or FOR ALL TABLES, or FOR ALL SEQUENCES.
    
    ~~~
    
    (29.7.2. Refreshing Stale Sequences)
    
    4.
    +   <para>
    +    To verify, compare the sequences values between the publisher and
    +    subscriber, and if necessary, execute
    +    <link linkend="sql-altersubscription-params-refresh-publication-sequences">
    +    <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES</command></link>.
    +   </para>
    
    /sequences values/sequence values/
    
    Should we elaborate or give an example here, exactly how the user
    should "compare the sequence values between the publisher and
    subscriber".
    
    ~~~
    
    (29.9. Restrictions)
    
    5.
    +     On the subscriber, a sequence will retain the last value it synchronized
    +     from the publisher either during the initial
    +     <command>CREATE SUBSCRIPTION</command> or
    +     <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES</command>.
    
    You haven't mentioned ALTER SUBSCRIPTION ... REFRESH PUBLICATION, but
    AFAIK that could also synchronize the latest values for any newly
    added sequences. It seems a bit tedious to name all these commands all
    the time, but I am not sure if there is a better way.
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    6.
    +         <para>
    +          See <xref linkend="sequence-definition-mismatches"/> for
    recommendations on how
    +          to handle any warnings about sequence definition differences between
    +          the publisher and the subscriber, which might occur when
    +          <literal>copy_data = true</literal>.
    +         </para>
    
    I have a question about functionality: I understand we do not actually
    "synchronize" sequence data at this time if the copy_data=false, but
    OTOH, shouldn't we still be checking (and WARNING) if there are any
    pub/sub sequences difference detected, regardless of the copy_data
    bool value? Otherwise, I think all we are doing is deferring the
    checking/warning until later (e.g. during REFRESH PUBLICATION
    SEQUENCES). Isn't it is better to get the warning earlier so the user
    can fix it earlier?
    
    ======
    doc/src/sgml/ref/create_subscription.sgml
    
    7.
    +         <para>
    +          See <xref linkend="sequence-definition-mismatches"/>
    +          for recommendations on how to handle any warnings about sequence
    +          definition differences between the publisher and the subscriber,
    +          which might occur when <literal>copy_data = true</literal>.
    +         </para>
    
    ditto previous review comment #6.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  205. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-04-22T06:10:02Z

    On Thu, 17 Apr 2025 at 13:52, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > No comments for patch v20250416-0001
    > No comments for patch v20250416-0002
    > No comments for patch v20250416-0003
    >
    > Here are some comments for patch v20250416-0004
    >
    > ======
    > src/backend/catalog/system_views.sql
    >
    > 1.
    > +CREATE VIEW pg_publication_sequences AS
    > +    SELECT
    > +        P.pubname AS pubname,
    > +        N.nspname AS schemaname,
    > +        C.relname AS sequencename
    > +    FROM pg_publication P,
    > +         LATERAL pg_get_publication_sequences(P.pubname) GPS,
    > +         pg_class C JOIN pg_namespace N ON (N.oid = C.relnamespace)
    > +    WHERE C.oid = GPS.relid;
    > +
    >
    > Should we have some regression tests for this view?
    >
    > SUGGESTION
    > test_pub=# CREATE SEQUENCE S1;
    > test_pub=# CREATE SEQUENCE S2;
    > test_pub=# CREATE PUBLICATION PUB1 FOR ALL SEQUENCES;
    > test_pub=# SELECT * FROM pg_publication_sequences;
    >  pubname | schemaname | sequencename
    > ---------+------------+--------------
    >  pub1    | public     | s1
    >  pub1    | public     | s2
    > (2 rows)
    
    I felt it is not required, as this will be verified from create/alter
    subscription.
    
    > ======
    > src/bin/pg_dump/pg_dump.c
    >
    > getSubscriptionRelations:
    >
    > Vignesh 16/4 answered my previous review comment #25:
    > You are talking about the error message right, I have changed that.
    >
    > PS REPLY 17/4
    > Yes, the error message, but also I thought 'tblinfo' var and
    > FindTableByOid function name should refer to relations instead of
    > tables?
    
    I felt no need to change these things and bring a lot of differences
    between the back branches.
    
    The rest of the comments were fixed.
    
    Regarding the below comments from [1].
    4.
    +   <para>
    +    To verify, compare the sequences values between the publisher and
    +    subscriber, and if necessary, execute
    +    <link linkend="sql-altersubscription-params-refresh-publication-sequences">
    +    <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES</command></link>.
    +   </para>
    
    /sequences values/sequence values/
    
    Should we elaborate or give an example here, exactly how the user
    should "compare the sequence values between the publisher and
    subscriber".
    
    I felt it was obvious, so no  need for an example in this case.
    
    6.
    +         <para>
    +          See <xref linkend="sequence-definition-mismatches"/> for
    recommendations on how
    +          to handle any warnings about sequence definition differences between
    +          the publisher and the subscriber, which might occur when
    +          <literal>copy_data = true</literal>.
    +         </para>
    
    I have a question about functionality: I understand we do not actually
    "synchronize" sequence data at this time if the copy_data=false, but
    OTOH, shouldn't we still be checking (and WARNING) if there are any
    pub/sub sequences difference detected, regardless of the copy_data
    bool value? Otherwise, I think all we are doing is deferring the
    checking/warning until later (e.g. during REFRESH PUBLICATION
    SEQUENCES). Isn't it is better to get the warning earlier so the user
    can fix it earlier?
    
    I noticed the similar case with tables.
    example:
    pub:
    create table t1(c1 int, c2 int);
    create publication pub1 for table t1;
    sub:
    create table t1(c1 int);
    create subscription sub1 connection ... publication pub1 with (copy_data=off);
    
    In this case, we will not detect the error during create subscription
    but at a later insert.
    As the suggested case is similar to above, I felt it is ok.
    
    ======
    doc/src/sgml/ref/create_subscription.sgml
    
    7.
    +         <para>
    +          See <xref linkend="sequence-definition-mismatches"/>
    +          for recommendations on how to handle any warnings about sequence
    +          definition differences between the publisher and the subscriber,
    +          which might occur when <literal>copy_data = true</literal>.
    +         </para>
    
    ditto previous review comment #6.
    
    This is similar to the above comment.
    
    The rest of the comments were fixed. The attached v20250422 version
    patch has the changes for the same.
    [1] - https://www.postgresql.org/message-id/CAHut+Ps2LzJwPGB8i2_ViS9c9VxeAeqDqvH5R8E-M8HvWeNfAQ@mail.gmail.com
    
    Regards,
    Vignesh
    
  206. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-23T06:07:04Z

    Hi Vignesh.
    
    Review comments for patch v20250422-0001.
    
    ======
    Commit message
    
    1.
    This patch introduces a new function: pg_sequence_state function
    allows retrieval of sequence values including LSN.
    
    SUGGESTION
    This patch introduces a new function, 'pg_sequence_state', which
    allows retrieval of sequence values, including the associated LSN.
    
    ======
    src/backend/commands/sequence.c
    
    pg_sequence_state:
    
    2.
    + ereport(ERROR,
    + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    + errmsg("permission denied for sequence %s",
    + RelationGetRelationName(seqrel))));
    
    Has redundant parentheses.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  207. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-23T23:36:57Z

    Hi Vignesh,
    
    Some review comments for patch v20250422-0003.
    
    ======
    src/backend/replication/logical/syncutils.c
    
    1.
    +/*
    + * Exit routine for synchronization worker.
    + */
    +pg_noreturn void
    +SyncFinishWorker(void)
    
    Why does this have the pg_noreturn annotation? None of the other void
    functions do.
    
    ~~~
    
    2.
    +bool
    +FetchRelationStates(bool *started_tx)
    
    All the functions in the sync utils.c are named like Syncxxx, so for
    consistency, why not name this one also?
    e.g. /FetchRelationStates/SyncFetchRelationStates/
    
    ======
    src/backend/replication/logical/tablesync.c
    
    3.
    -static bool
    -wait_for_relation_state_change(Oid relid, char expected_state)
    +bool
    +WaitForRelationStateChange(Oid relid, char expected_state)
     {
      char state;
    ~
    
    3a.
    Why isn't this static, like before?
    
    ~
    
    3b.
    If it is *only* for tables and nothing else, shouldn't it be static
    and have a function name like 'wait_for_table_state_change' (not
    _relation_)?
    OTOH, if there is potential for this to be used for sequences in
    future, then it should be in the syncutils.c module with a name like
    'SyncWaitForRelationStateChange'.
    
    ======
    src/include/replication/worker_internal.h
    
    4.
    @@ -250,6 +252,7 @@ extern void logicalrep_worker_stop(Oid subid, Oid relid);
     extern void logicalrep_pa_worker_stop(ParallelApplyWorkerInfo *winfo);
     extern void logicalrep_worker_wakeup(Oid subid, Oid relid);
     extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker);
    +pg_noreturn extern void SyncFinishWorker(void);
    
     extern int logicalrep_sync_worker_count(Oid subid);
    
    @@ -259,9 +262,13 @@ extern void
    ReplicationOriginNameForLogicalRep(Oid suboid, Oid relid,
     extern bool AllTablesyncsReady(void);
     extern void UpdateTwoPhaseState(Oid suboid, char new_state);
    
    -extern void process_syncing_tables(XLogRecPtr current_lsn);
    -extern void invalidate_syncing_table_states(Datum arg, int cacheid,
    - uint32 hashvalue);
    +extern bool FetchRelationStates(bool *started_tx);
    +extern bool WaitForRelationStateChange(Oid relid, char expected_state);
    +extern void ProcessSyncingTablesForSync(XLogRecPtr current_lsn);
    +extern void ProcessSyncingTablesForApply(XLogRecPtr current_lsn);
    +extern void SyncProcessRelations(XLogRecPtr current_lsn);
    +extern void SyncInvalidateRelationStates(Datum arg, int cacheid,
    + uint32 hashvalue);
    
    ~
    
    4a.
    Why does SyncFinishWorker have the pg_noreturn annotation? None of the
    other void functions do.
    
    ~
    
    4b.
    I felt that all the SyncXXX functions exposed from syncutils.c should
    be grouped together, and maybe even with a comment like /* from
    syncutils.c */
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  208. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-24T06:06:49Z

    Hi Vignesh,
    
    Some comments for v20250422-0004.
    
    ======
    src/backend/commands/sequence.c
    
    pg_sequence_state:
    
    1.
    + * The page_lsn will be utilized in logical replication sequence
    + * synchronization to record the page_lsn of sequence in the
    pg_subscription_rel
    + * system catalog. It will reflect the page_lsn of the remote sequence at the
    + * moment it was synchronized.
    + *
    
    SUGGESTION (minor rewording)
    The page LSN will be used in logical replication of sequences to
    record the LSN of the sequence page in the pg_subscription_rel system
    catalog.  It reflects the LSN of the remote sequence at the time it
    was synchronized.
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    AlterSubscription:
    
    2.
    - case ALTER_SUBSCRIPTION_REFRESH:
    + case ALTER_SUBSCRIPTION_REFRESH_PUBLICATION_SEQUENCES:
    + {
    + if (!sub->enabled)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES is not
    allowed for disabled subscriptions"));
    +
    + PreventInTransactionBlock(isTopLevel, "ALTER SUBSCRIPTION ...
    REFRESH PUBLICATION SEQUENCES");
    +
    + AlterSubscription_refresh(sub, true, NULL, false, true, true);
    +
    + break;
    + }
    +
    + case ALTER_SUBSCRIPTION_REFRESH_PUBLICATION:
    
    I felt these should be reordered so REFRESH PUBLICATION comes before
    REFRESH PUBLICATION SEQUENCES. No particular reason, but AFAICT that
    is how you've ordered them in all other places -- eg, gram.y, the
    documentation, etc. -- so let's be consistent.
    
    ======
    src/backend/replication/logical/launcher.c
    
    3.
    +/*
    + * Update the failure time of the sequencesync worker in the subscription's
    + * apply worker.
    + *
    + * This function is invoked when the sequencesync worker exits due to a
    + * failure.
    + */
    +void
    +logicalrep_seqsyncworker_failuretime(int code, Datum arg)
    
    It might be better to call this function name
    'logicalrep_seqsyncworker_failure' (not _failuretime) because it is
    more generic, and in future, you might want to do more things in this
    function apart from just setting the failure time.
    
    ======
    src/backend/replication/logical/syncutils.c
    
    SyncFinishWorker:
    
    4.
    + /* This is a clean exit, so no need to set a sequence failure time. */
    + if (wtype == WORKERTYPE_SEQUENCESYNC)
    + cancel_before_shmem_exit(logicalrep_seqsyncworker_failuretime, 0);
    +
    
    I didn't think the comment should mention setting 'failure time'.
    Those details belong at a lower level -- here, it is better to be more
    generic.
    
    SUGGESTION:
    /* This is a clean exit, so no need for any sequence failure logic. */
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  209. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-04-24T10:29:46Z

    On Thu, 24 Apr 2025 at 05:07, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Some review comments for patch v20250422-0003.
    >
    > ======
    > src/backend/replication/logical/syncutils.c
    >
    > 1.
    > +/*
    > + * Exit routine for synchronization worker.
    > + */
    > +pg_noreturn void
    > +SyncFinishWorker(void)
    >
    > Why does this have the pg_noreturn annotation? None of the other void
    > functions do.
    
    It indicates that the function will not return control flow to the
    calling function after it finishes. This is not a new function, it was
    just moved from tablesync.c
    > ======
    > src/include/replication/worker_internal.h
    >
    > 4.
    > @@ -250,6 +252,7 @@ extern void logicalrep_worker_stop(Oid subid, Oid relid);
    >  extern void logicalrep_pa_worker_stop(ParallelApplyWorkerInfo *winfo);
    >  extern void logicalrep_worker_wakeup(Oid subid, Oid relid);
    >  extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker);
    > +pg_noreturn extern void SyncFinishWorker(void);
    >
    >  extern int logicalrep_sync_worker_count(Oid subid);
    >
    > @@ -259,9 +262,13 @@ extern void
    > ReplicationOriginNameForLogicalRep(Oid suboid, Oid relid,
    >  extern bool AllTablesyncsReady(void);
    >  extern void UpdateTwoPhaseState(Oid suboid, char new_state);
    >
    > -extern void process_syncing_tables(XLogRecPtr current_lsn);
    > -extern void invalidate_syncing_table_states(Datum arg, int cacheid,
    > - uint32 hashvalue);
    > +extern bool FetchRelationStates(bool *started_tx);
    > +extern bool WaitForRelationStateChange(Oid relid, char expected_state);
    > +extern void ProcessSyncingTablesForSync(XLogRecPtr current_lsn);
    > +extern void ProcessSyncingTablesForApply(XLogRecPtr current_lsn);
    > +extern void SyncProcessRelations(XLogRecPtr current_lsn);
    > +extern void SyncInvalidateRelationStates(Datum arg, int cacheid,
    > + uint32 hashvalue);
    >
    > ~
    >
    > 4a.
    > Why does SyncFinishWorker have the pg_noreturn annotation? None of the
    > other void functions do.
    
    This is same as comment #1
    
    The rest of the comments were fixed.
    Also the comments from [1] and [2] are fixed in the attached v20250424 version.
    [1] - https://www.postgresql.org/message-id/CAHut%2BPticXRg4_W%3Dd7H37DWPh5LNePbcQ5RKc3vUW5HCzAX_fg%40mail.gmail.com
    [2] - https://www.postgresql.org/message-id/CAHut%2BPtBhb89%2B1DAYUFc%3D1Ojkh1mHro%2Bg3UCqMZAQoSpPQoqZA%40mail.gmail.com
    
    Regards,
    Vignesh
    
  210. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-26T08:50:43Z

    Hi Vignesh.
    
    FYI, patch v20250424-0004 reported whitespace errors when applied.
    
    [postgres@CentOS7-x64 oss_postgres_misc]$ git apply
    ../patches_misc/v20250424-0004-Enhance-sequence-synchronization-during-su.patch
    ../patches_misc/v20250424-0004-Enhance-sequence-synchronization-during-su.patch:366:
    trailing whitespace.
     *
    warning: 1 line adds whitespace errors.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  211. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-26T08:54:16Z

    Hi Vignesh.
    
    Some review comments for v20250426-0005.
    
    ======
    doc/src/sgml/catalogs.sgml
    
    1.
           <para>
    -       State code:
    +       State code for tables:
            <literal>i</literal> = initialize,
            <literal>d</literal> = data is being copied,
            <literal>f</literal> = finished table copy,
            <literal>s</literal> = synchronized,
            <literal>r</literal> = ready (normal replication)
    +      </para>
    +      <para>
    +       State code for sequences:
    +       <literal>i</literal> = initialize,
    +       <literal>r</literal> = ready
           </para></entry>
    
    1a.
    There should be an introductory sentence to say what this field is.
    e.g. "State code for the table or sequence."
    
    ~
    
    1b.
    /State code for tables/State codes for tables/
    
    ~
    
    1c.
    /State code for sequences/State codes for sequences/
    
    ======
    doc/src/sgml/logical-replication.sgml
    
    2.
    +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, sequences
    allow users
    +   to synchronize their current state at any given time. For more information,
    +   refer to <xref linkend="logical-replication-sequences"/>.
    
    This is OK, but maybe the "sequences allow users..." is worded
    strangely. How about below?
    
    SUGGESTION
    Unlike tables, the current state of sequences may be synchronised at any time.
    
    ~~~
    
    3.
    +     Incremental sequence changes are not replicated.  The data in serial or
    +     identity columns backed by sequences will of course be replicated as part
    +     of the table, the sequences themselves do not replicate ongoing changes.
    
    Seems to be a missing word here
    
    /The data in serial/Although the data in serial/
    
    OR
    
    Just change the punctuation to a semicolon.
    /of the table,/of the table;/
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    4.
    +         <para>
    +          Previously subscribed sequences are not re-synchronized. To do that,
    +          see <link
    linkend="sql-altersubscription-params-refresh-publication-sequences">
    +          <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES</command></link>
    +         </para>
    
    4a.
    Missing period in the last sentence.
    
    ~
    
    4b.
    AFAIK, when copy_data=false, then not only will *existing* sequences
    not be synchronised, but even the *new* sequences will not be
    synchronised. Effectively, when copy_data = false, then nothing at all
    happens for sequences as far as what the user sees, right?
    
    Experiment:
    
    test_pub=# create publication pub1 for all sequences;
    CREATE PUBLICATION
    
    test_sub=# create sequence s1;
    CREATE SEQUENCE
    NOTICE:  created replication slot "sub1" on publisher
    CREATE SUBSCRIPTION
    
    test_pub=# create sequence s1;
    CREATE SEQUENCE
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           1
    (1 row)
    
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           2
    (1 row)
    
    test_pub=# select * from nextval('s1');
     nextval
    ---------
           3
    (1 row)
    
    test_sub=# alter subscription sub1 refresh publication with (copy_data=false);
    ALTER SUBSCRIPTION
    
    test_sub=# select * from s1;
     last_value | log_cnt | is_called
    ------------+---------+-----------
              1 |       0 | f
    (1 row)
    
    So, subscriber side s1 is unaffected.
    
    Maybe it is not worth the effort, but doesn't this mean that you could
    optimise the AlterSubscription_refresh() logic to completely skip all
    processing for sequences when copy_data=false. e.g. what's the point
    of gathering publisher sequence lists and setting INIT states for
    them, etc, when it won't synchronise anything because copy_data=false?
    Everything will be synchronised later anyway when the user does
    REFRESH PUBLICATION SEQUENCES.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  212. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-04-28T12:56:56Z

    On Sat, 26 Apr 2025 at 14:24, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh.
    >
    > Some review comments for v20250426-0005.
    >
    > 4b.
    > AFAIK, when copy_data=false, then not only will *existing* sequences
    > not be synchronised, but even the *new* sequences will not be
    > synchronised. Effectively, when copy_data = false, then nothing at all
    > happens for sequences as far as what the user sees, right?
    >
    > Experiment:
    >
    > test_pub=# create publication pub1 for all sequences;
    > CREATE PUBLICATION
    >
    > test_sub=# create sequence s1;
    > CREATE SEQUENCE
    > NOTICE:  created replication slot "sub1" on publisher
    > CREATE SUBSCRIPTION
    >
    > test_pub=# create sequence s1;
    > CREATE SEQUENCE
    > test_pub=# select * from nextval('s1');
    >  nextval
    > ---------
    >        1
    > (1 row)
    >
    > test_pub=# select * from nextval('s1');
    >  nextval
    > ---------
    >        2
    > (1 row)
    >
    > test_pub=# select * from nextval('s1');
    >  nextval
    > ---------
    >        3
    > (1 row)
    >
    > test_sub=# alter subscription sub1 refresh publication with (copy_data=false);
    > ALTER SUBSCRIPTION
    >
    > test_sub=# select * from s1;
    >  last_value | log_cnt | is_called
    > ------------+---------+-----------
    >           1 |       0 | f
    > (1 row)
    >
    > So, subscriber side s1 is unaffected.
    >
    > Maybe it is not worth the effort, but doesn't this mean that you could
    > optimise the AlterSubscription_refresh() logic to completely skip all
    > processing for sequences when copy_data=false. e.g. what's the point
    > of gathering publisher sequence lists and setting INIT states for
    > them, etc, when it won't synchronise anything because copy_data=false?
    > Everything will be synchronised later anyway when the user does
    > REFRESH PUBLICATION SEQUENCES.
    
    Currently this is in line with table behavior, I felt let's keep it
    that way so that it will be easier to extend sequence replication as
    use cases grow and will become more in sync with tables.
    
    The rest of the comments were fixed, the attached v20250428 version
    patch has the changes for the same.
    Also the issue reported at [1] is available in the attached patch.
    [1] - https://www.postgresql.org/message-id/CAHut%2BPujY8Xd%3DT94zuPuF21s0dLRGVJaXgRnLbGE47pwSpo-YA%40mail.gmail.com
    
    Regards,
    Vignesh
    
  213. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-04-29T00:44:57Z

    Hi Vignesh.
    
    Some trivial review comments for DOCS patch v20250428-0005.
    
    ======
    doc/src/sgml/logical-replication.sgml
    
    1.
    +   Publications may currently only contain tables or sequences. Objects must be
    +   added explicitly, except when a publication is created using
    +   <literal>FOR TABLES IN SCHEMA</literal>, or <literal>FOR ALL
    TABLES</literal>,
    +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    +   sequences may be synchronised at any time. For more information, refer to
    +   <xref linkend="logical-replication-sequences"/>.
       </para>
    
    AFAIK the PostgreSQL documentation uses US spelling:
    
    /synchronised/synchronized/
    
    ~~~
    
    2.
    +     Incremental sequence changes are not replicated.  Although the data in
    +     serial or identity columns backed by sequences will of course be
    +     replicated as part of the table, the sequences themselves do not replicate
    +     ongoing changes. On the subscriber, a sequence will retain the last value
    
    I didn't think that you needed to say "of course" here.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  214. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-01T03:16:27Z

    On Tue, 29 Apr 2025 at 06:15, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh.
    >
    > Some trivial review comments for DOCS patch v20250428-0005.
    >
    > ======
    > doc/src/sgml/logical-replication.sgml
    >
    > 1.
    > +   Publications may currently only contain tables or sequences. Objects must be
    > +   added explicitly, except when a publication is created using
    > +   <literal>FOR TABLES IN SCHEMA</literal>, or <literal>FOR ALL
    > TABLES</literal>,
    > +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    > +   sequences may be synchronised at any time. For more information, refer to
    > +   <xref linkend="logical-replication-sequences"/>.
    >    </para>
    >
    > AFAIK the PostgreSQL documentation uses US spelling:
    >
    > /synchronised/synchronized/
    >
    > ~~~
    >
    > 2.
    > +     Incremental sequence changes are not replicated.  Although the data in
    > +     serial or identity columns backed by sequences will of course be
    > +     replicated as part of the table, the sequences themselves do not replicate
    > +     ongoing changes. On the subscriber, a sequence will retain the last value
    >
    > I didn't think that you needed to say "of course" here.
    
    Thanks for the comments, the updated patch has the changes for the same.
    
    Regards,
    Vignesh
    
  215. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-03T13:57:36Z

    On Thu, 1 May 2025 at 08:46, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 29 Apr 2025 at 06:15, Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > Hi Vignesh.
    > >
    > > Some trivial review comments for DOCS patch v20250428-0005.
    > >
    > > ======
    > > doc/src/sgml/logical-replication.sgml
    > >
    > > 1.
    > > +   Publications may currently only contain tables or sequences. Objects must be
    > > +   added explicitly, except when a publication is created using
    > > +   <literal>FOR TABLES IN SCHEMA</literal>, or <literal>FOR ALL
    > > TABLES</literal>,
    > > +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    > > +   sequences may be synchronised at any time. For more information, refer to
    > > +   <xref linkend="logical-replication-sequences"/>.
    > >    </para>
    > >
    > > AFAIK the PostgreSQL documentation uses US spelling:
    > >
    > > /synchronised/synchronized/
    > >
    > > ~~~
    > >
    > > 2.
    > > +     Incremental sequence changes are not replicated.  Although the data in
    > > +     serial or identity columns backed by sequences will of course be
    > > +     replicated as part of the table, the sequences themselves do not replicate
    > > +     ongoing changes. On the subscriber, a sequence will retain the last value
    > >
    > > I didn't think that you needed to say "of course" here.
    >
    > Thanks for the comments, the updated patch has the changes for the same.
    
    There was one pending open comment #6 from [1]. This has been
    addressed in the attached patch.
    [1] - https://www.postgresql.org/message-id/OSCPR01MB14966DA8CB749A0D4E9F3F7A7F50E2%40OSCPR01MB14966.jpnprd01.prod.outlook.com
    
    Regards,
    Vignesh
    
  216. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-05-09T08:58:15Z

    On Sat, May 3, 2025 at 7:27 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > >
    > > Thanks for the comments, the updated patch has the changes for the same.
    >
    
    Thanks for the patches. Please find few comments:
    
    
    1)
    patch004 commit msg:
    - Drop published sequences are removed from pg_subscription_rel.
    
    Drop -->Dropped
    
    
    2)
    copy_sequences:
    
    LOG:  Executing query :SELECT s.schname, s.seqname, ps.*, seq.seqtypid,
           seq.seqstart, seq.seqincrement, seq.seqmin,
           seq.seqmax, seq.seqcycle
    FROM ( VALUES ('public', 'myseq1'), ('public', 'myseq3') ) AS s
    (schname, seqname)
    JOIN LATERAL pg_sequence_state(s.schname, s.seqname) ps ON true
    ....
    
    Do we really need to log this query? If so, shall it be DEBUG1/DEBUG2?
    
    
    3)
    In log, we get:
    
    ------------------
    LOG:  logical replication synchronized 9 of 9 sequences for subscription "sub1"
    WARNING:  parameters differ for the remote and local sequences
    ("public.myseq1", "public.myseq3") for subscription "sub1"
    
    LOG:  logical replication synchronized 2 of 2 sequences for subscription "sub1"
    WARNING:  parameters differ for the remote and local sequences
    ("public.myseq1", "public.myseq3") for subscription "sub1"
    ------------------
    
    This is confusing. I have 9 sequences, out of which 2 are mismatched.
    So on REFRESH I get the first message as 'synchronized 9 of 9' and
    later when it attempts to resynchronize pending ones automatically, it
    keeps on displaying  'synchronized 2 of 2'.
    
    Can we mention something like below:
    -----------------
    Unsynchronized sequences: 9, attempted in this batch: 9, succedded: 7,
    mismatched/failed:2
    
    So that if it is more than 100, say 120, it will say:
    Unsynchronized sequences: 120, attempted in this batch: 100,
    succedded: 98, mismatched/failed:2
    And in next batch:
    Unsynchronized sequences: 120, attempted in this batch: 20, succedded:
    20, mismatched:0
    
    And while attempting to synchronize failed ones, it will say:
    Unsynchronized sequences: 2, attempted in this batch: 2, succedded: 0,
    mismatched:2
    -----------------
    
    Please feel free to change the words. The intent is to get a clear
    picture on what is happening.
    
    
    4)
    Why in patch001, we have 'pg_sequence_state' with one argument while
    in 4ht patch it is changed to 2 args? Is it intentional to have it the
    current way in patch001?
    
    
    5)
    Section1:
      <para>
       A new <firstterm>sequence synchronization worker</firstterm> will be started
       after executing any of the above subscriber commands, and will exit once the
       sequences are synchronized.
      </para>
    
    Section2:
      <sect2 id="sequence-definition-mismatches">
       <title>Sequence Definition Mismatches</title>
       <warning>
        <para>
         During sequence synchronization, the sequence definitions of the publisher
         and the subscriber are compared. A WARNING is logged if any differences
         are detected.
        </para>
       </warning>
    
    
    None of the section mentions that the synchronization worker will keep
    on attempting to synchronize the failed/mismtached sequences until the
    differences are resolved (provided disable_on_error is not enabled).
    I think we can mention such a thing briefly in
    'sequence-definition-mismatches' section.
    
    
    thanks
    Shveta
    
    
    
    
  217. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-05-14T04:25:42Z

    On Sat, May 3, 2025 at 7:28 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > There was one pending open comment #6 from [1]. This has been
    > addressed in the attached patch.
    
    Thank you for the patches, here are my comments for patch-004: sequencesync.c
    
    copy_sequences()
    -------------------
    1)
    + if (first)
    + first = false;
    + else
    + appendStringInfoString(seqstr, ", ");
    
    We can avoid additional variable here, suggestion -
    if (seqstr->len > 0)
      appendStringInfoString(seqstr, ", ");
    ~~~~
    
    2)
    + else
    + {
    + *sequence_sync_error = true;
    + append_mismatched_sequences(mismatched_seqs, seqinfo);
    + }
    
    I think *sequence_sync_error = true can be removed from here, as we
    can avoid setting it for every mismatch, as it is already set at the
    end of the function if any sequence mismatches are found.
    ~~~~
    
    3)
    + if (message_level_is_interesting(DEBUG1))
    + {
    + /* LOG all the sequences synchronized during current batch. */
    + for (int i = 0; i < curr_batch_seq_count; i++)
    + {
    + LogicalRepSequenceInfo *done_seq;
    ...
    +
    + ereport(DEBUG1,
    + errmsg_internal("logical replication synchronization for
    subscription \"%s\", sequence \"%s\" has finished",
    + get_subscription_name(subid, false),
    + done_seq->seqname));
    + }
    + }
    
    3a) I think the DEBUG1 log can be moved inside the while loop just
    above, to avoid traversing the list again unnecessarily.
    ~~~~
    
    LogicalRepSyncSequences():
    -----------------------------
    4)
    + /*
    + * Sequence synchronization failed due to a parameter mismatch. Set the
    + * failure time to prevent immediate initiation of the sequencesync
    + * worker.
    + */
    + if (sequence_sync_error)
    + {
    + logicalrep_seqsyncworker_set_failuretime();
    + ereport(LOG,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("sequence synchronization failed because the parameters
    between the publisher and subscriber do not match for all
    sequences"));
    + }
    
    I think saying "sequence synchronization failed" could be misleading,
    as the matched sequences will still be synced successfully. It might
    be clearer to reword it to something like:
    "sequence synchronization failed for some sequences because the
    parameters between the publisher and subscriber do not match."
    ~~~~
    
    --
    Thanks,
    Nisha
    
    
    
    
  218. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-14T04:56:31Z

    On Fri, 9 May 2025 at 14:28, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Sat, May 3, 2025 at 7:27 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > >
    > > > Thanks for the comments, the updated patch has the changes for the same.
    > >
    >
    > Thanks for the patches. Please find few comments:
    >
    >
    > 1)
    > patch004 commit msg:
    > - Drop published sequences are removed from pg_subscription_rel.
    >
    > Drop -->Dropped
    
    Modified
    
    > 2)
    > copy_sequences:
    >
    > LOG:  Executing query :SELECT s.schname, s.seqname, ps.*, seq.seqtypid,
    >        seq.seqstart, seq.seqincrement, seq.seqmin,
    >        seq.seqmax, seq.seqcycle
    > FROM ( VALUES ('public', 'myseq1'), ('public', 'myseq3') ) AS s
    > (schname, seqname)
    > JOIN LATERAL pg_sequence_state(s.schname, s.seqname) ps ON true
    > ....
    >
    > Do we really need to log this query? If so, shall it be DEBUG1/DEBUG2?
    
    This is not required, removed it
    
    > 3)
    > In log, we get:
    >
    > ------------------
    > LOG:  logical replication synchronized 9 of 9 sequences for subscription "sub1"
    > WARNING:  parameters differ for the remote and local sequences
    > ("public.myseq1", "public.myseq3") for subscription "sub1"
    >
    > LOG:  logical replication synchronized 2 of 2 sequences for subscription "sub1"
    > WARNING:  parameters differ for the remote and local sequences
    > ("public.myseq1", "public.myseq3") for subscription "sub1"
    > ------------------
    >
    > This is confusing. I have 9 sequences, out of which 2 are mismatched.
    > So on REFRESH I get the first message as 'synchronized 9 of 9' and
    > later when it attempts to resynchronize pending ones automatically, it
    > keeps on displaying  'synchronized 2 of 2'.
    >
    > Can we mention something like below:
    > -----------------
    > Unsynchronized sequences: 9, attempted in this batch: 9, succedded: 7,
    > mismatched/failed:2
    >
    > So that if it is more than 100, say 120, it will say:
    > Unsynchronized sequences: 120, attempted in this batch: 100,
    > succedded: 98, mismatched/failed:2
    > And in next batch:
    > Unsynchronized sequences: 120, attempted in this batch: 20, succedded:
    > 20, mismatched:0
    >
    > And while attempting to synchronize failed ones, it will say:
    > Unsynchronized sequences: 2, attempted in this batch: 2, succedded: 0,
    > mismatched:2
    > -----------------
    >
    > Please feel free to change the words. The intent is to get a clear
    > picture on what is happening.
    
    Fixed this
    
    > 4)
    > Why in patch001, we have 'pg_sequence_state' with one argument while
    > in 4ht patch it is changed to 2 args? Is it intentional to have it the
    > current way in patch001?
    
    This should have been in 001 itself, moved these changes to 001 patch
    
    > 5)
    > Section1:
    >   <para>
    >    A new <firstterm>sequence synchronization worker</firstterm> will be started
    >    after executing any of the above subscriber commands, and will exit once the
    >    sequences are synchronized.
    >   </para>
    >
    > Section2:
    >   <sect2 id="sequence-definition-mismatches">
    >    <title>Sequence Definition Mismatches</title>
    >    <warning>
    >     <para>
    >      During sequence synchronization, the sequence definitions of the publisher
    >      and the subscriber are compared. A WARNING is logged if any differences
    >      are detected.
    >     </para>
    >    </warning>
    >
    >
    > None of the section mentions that the synchronization worker will keep
    > on attempting to synchronize the failed/mismtached sequences until the
    > differences are resolved (provided disable_on_error is not enabled).
    > I think we can mention such a thing briefly in
    > 'sequence-definition-mismatches' section.
    
    Modified
    
    The attached v20250514 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  219. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-14T04:59:13Z

    On Wed, 14 May 2025 at 09:55, Nisha Moond <nisha.moond412@gmail.com> wrote:
    >
    > On Sat, May 3, 2025 at 7:28 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > >
    > > There was one pending open comment #6 from [1]. This has been
    > > addressed in the attached patch.
    >
    > Thank you for the patches, here are my comments for patch-004: sequencesync.c
    >
    > copy_sequences()
    > -------------------
    > 1)
    > + if (first)
    > + first = false;
    > + else
    > + appendStringInfoString(seqstr, ", ");
    >
    > We can avoid additional variable here, suggestion -
    > if (seqstr->len > 0)
    >   appendStringInfoString(seqstr, ", ");
    
    Modified
    
    > 2)
    > + else
    > + {
    > + *sequence_sync_error = true;
    > + append_mismatched_sequences(mismatched_seqs, seqinfo);
    > + }
    >
    > I think *sequence_sync_error = true can be removed from here, as we
    > can avoid setting it for every mismatch, as it is already set at the
    > end of the function if any sequence mismatches are found.
    
    Modified
    
    > 3)
    > + if (message_level_is_interesting(DEBUG1))
    > + {
    > + /* LOG all the sequences synchronized during current batch. */
    > + for (int i = 0; i < curr_batch_seq_count; i++)
    > + {
    > + LogicalRepSequenceInfo *done_seq;
    > ...
    > +
    > + ereport(DEBUG1,
    > + errmsg_internal("logical replication synchronization for
    > subscription \"%s\", sequence \"%s\" has finished",
    > + get_subscription_name(subid, false),
    > + done_seq->seqname));
    > + }
    > + }
    >
    > 3a) I think the DEBUG1 log can be moved inside the while loop just
    > above, to avoid traversing the list again unnecessarily.
    
    Modified
    
    > LogicalRepSyncSequences():
    > -----------------------------
    > 4)
    > + /*
    > + * Sequence synchronization failed due to a parameter mismatch. Set the
    > + * failure time to prevent immediate initiation of the sequencesync
    > + * worker.
    > + */
    > + if (sequence_sync_error)
    > + {
    > + logicalrep_seqsyncworker_set_failuretime();
    > + ereport(LOG,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("sequence synchronization failed because the parameters
    > between the publisher and subscriber do not match for all
    > sequences"));
    > + }
    >
    > I think saying "sequence synchronization failed" could be misleading,
    > as the matched sequences will still be synced successfully. It might
    > be clearer to reword it to something like:
    > "sequence synchronization failed for some sequences because the
    > parameters between the publisher and subscriber do not match."
    
    Modified
    
    The comments are fixed in the v20250514 version patch attached at [1].
    
    [1] - https://www.postgresql.org/message-id/CALDaNm3GXa-kKTe3oqmKA8oniHvZfgYUXG8mVczv4GJzFwG7bg%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  220. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-05-15T06:57:00Z

    Hi Vignesh.
    
    Some minor review comments for the patches in set v20250514.
    
    ======
    
    Patch 0001.
    
    1.1
    For function 'pg_sequence_state', the DOCS call the 2nd parameter
    'sequence_name', but the pg_proc.dat file calls it 'seq_name'. Should
    these be made the same?
    
    ////////////////////
    
    Patch 0004.
    
    pg_sequence_state:
    
    4.1
    
    - errmsg("sequence \"%s.%s\" does not exist",
    + errmsg("logical replication sequence \"%s.%s\" does not exist",
    
    Why isn't this change already be done in an early patch when this
    function was first implemented?
    
    ~~~
    
    copy_sequences:
    
    4.2
    
    +/*
    + * Copy existing data of sequnces from the publisher.
    + *
    
    Typo: "sequnces"
    
    ~~~
    
    4.3
    +{
    + int total_seq = list_length(remotesequences);
    + int curr_seq = 0;
    +
    +/*
    + * We batch synchronize multiple sequences per transaction, because the
    + * alternative of synchronizing each sequence individually incurs overhead of
    + * starting and committing transactions repeatedly. On the other hand, we want
    + * to avoid keeping this batch transaction open for extended periods so it is
    + * currently limited to 100 sequences per batch.
    + */
    +#define MAX_SEQUENCES_SYNC_PER_BATCH 100
    
    Wrong indent for block comment.
    
    ~~~
    
    4.4
    + if (res->status != WALRCV_OK_TUPLES)
    + ereport(ERROR,
    + errcode(ERRCODE_CONNECTION_FAILURE),
    + errmsg("could not receive list of sequences information from the
    publisher: %s",
    +    res->err));
    
    Should this say /sequences information/sequence information/
    
    ~~~
    
    4.5
    + ereport(LOG,
    + errmsg("Logical replication sequence synchronization - total
    unsynchronized: %d, attempted in this batch: %d; succeeded in this
    batch: %d; mismatched in this batch: %d for subscription: \"%s\"",
    +    total_seq, batch_seq_count, batch_success_count,
    +    batch_mismatch_count, get_subscription_name(subid, false)));
    +
    
    
    This errmsg seems backwards. I think it should be expressed like the
    other one immediately above. Also I think the information can be made
    shorter -- e.g. no need to say "in this batch" multiple times.
    
    SUGGESTION
    "Logical replication sequence synchronization for subscription \"%s\"
    - total unsynchronized: %d; batch #%d = %d attempted, %d succeeded, %d
    mismatched"
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  221. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-16T08:46:19Z

    On Thu, 15 May 2025 at 12:27, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh.
    >
    > Some minor review comments for the patches in set v20250514.
    >
    > ======
    >
    > Patch 0001.
    >
    > 1.1
    > For function 'pg_sequence_state', the DOCS call the 2nd parameter
    > 'sequence_name', but the pg_proc.dat file calls it 'seq_name'. Should
    > these be made the same?
    >
    > ////////////////////
    >
    > Patch 0004.
    >
    > pg_sequence_state:
    >
    > 4.1
    >
    > - errmsg("sequence \"%s.%s\" does not exist",
    > + errmsg("logical replication sequence \"%s.%s\" does not exist",
    >
    > Why isn't this change already be done in an early patch when this
    > function was first implemented?
    >
    > ~~~
    >
    > copy_sequences:
    >
    > 4.2
    >
    > +/*
    > + * Copy existing data of sequnces from the publisher.
    > + *
    >
    > Typo: "sequnces"
    >
    > ~~~
    >
    > 4.3
    > +{
    > + int total_seq = list_length(remotesequences);
    > + int curr_seq = 0;
    > +
    > +/*
    > + * We batch synchronize multiple sequences per transaction, because the
    > + * alternative of synchronizing each sequence individually incurs overhead of
    > + * starting and committing transactions repeatedly. On the other hand, we want
    > + * to avoid keeping this batch transaction open for extended periods so it is
    > + * currently limited to 100 sequences per batch.
    > + */
    > +#define MAX_SEQUENCES_SYNC_PER_BATCH 100
    >
    > Wrong indent for block comment.
    >
    > ~~~
    >
    > 4.4
    > + if (res->status != WALRCV_OK_TUPLES)
    > + ereport(ERROR,
    > + errcode(ERRCODE_CONNECTION_FAILURE),
    > + errmsg("could not receive list of sequences information from the
    > publisher: %s",
    > +    res->err));
    >
    > Should this say /sequences information/sequence information/
    >
    > ~~~
    >
    > 4.5
    > + ereport(LOG,
    > + errmsg("Logical replication sequence synchronization - total
    > unsynchronized: %d, attempted in this batch: %d; succeeded in this
    > batch: %d; mismatched in this batch: %d for subscription: \"%s\"",
    > +    total_seq, batch_seq_count, batch_success_count,
    > +    batch_mismatch_count, get_subscription_name(subid, false)));
    > +
    >
    >
    > This errmsg seems backwards. I think it should be expressed like the
    > other one immediately above. Also I think the information can be made
    > shorter -- e.g. no need to say "in this batch" multiple times.
    >
    > SUGGESTION
    > "Logical replication sequence synchronization for subscription \"%s\"
    > - total unsynchronized: %d; batch #%d = %d attempted, %d succeeded, %d
    > mismatched"
    
    Thanks for the comments, these are handled in the attached v20250516
    version patch.
    
    Regards,
    Vignesh
    
  222. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-05-20T03:05:26Z

    >
    > Thanks for the comments, these are handled in the attached v20250516
    > version patch.
    >
    
    Thanks for the patches. Here are my review comments -
    
    Patch-0004: src/backend/replication/logical/sequencesync.c
    
    The sequence count logic using curr_seq in copy_sequences() seems buggy.
    Currently, curr_seq is incremented based on the number of tuples
    received from the publisher inside the inner while loop.
    This means it's counting the number of sequences returned by the
    publisher, not the number of sequences processed locally. This can
    lead to two issues:
    
    1) Repeated syncing of sequences:
    If some sequences are missing on the publisher, curr_seq will reflect
    fewer items than expected, and subsequent batches may reprocess
    already-synced sequences. Because next batch will use curr_seq to get
    values from the list as -
    
      seqinfo = (LogicalRepSequenceInfo *)
    lfirst(list_nth_cell(remotesequences, curr_seq + i));
    
    Example:
    For 110 sequences(s1 to s110), if 5 (s1 to s5) are missing on the
    publisher in the first batch, curr_seq = 95. In the next cycle, we
    resync s95 to s99.
    ~~~~
    
    2) Risk of sequencesync worker getting stuck in infinite loop
    
    Consider a case where remotesequences has 10 sequences (s1–s10) need
    syncing, and concurrently s9, s10 are deleted on the publisher.
    
    Cycle 1:
    Publisher returns s1–s8. So curr_seq = 8.
    
    Cycle 2:
    Publisher query returns zero rows (as s9, s10 no longer exist).
    curr_seq stays at 8 and never advances.
    
    This causes the while (curr_seq < total_seq) loop to run forever.
    ~~~~
    
    I think curr_seq  should be incremented by batch_seq_count just
    outside the inner while loop.
    
    --
    Thanks,
    Nisha
    
    
    
    
  223. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-05-20T04:24:23Z

    On Tue, May 20, 2025 at 8:35 AM Nisha Moond <nisha.moond412@gmail.com> wrote:
    >
    > >
    > > Thanks for the comments, these are handled in the attached v20250516
    > > version patch.
    > >
    >
    > Thanks for the patches. Here are my review comments -
    >
    > Patch-0004: src/backend/replication/logical/sequencesync.c
    >
    > The sequence count logic using curr_seq in copy_sequences() seems buggy.
    > Currently, curr_seq is incremented based on the number of tuples
    > received from the publisher inside the inner while loop.
    > This means it's counting the number of sequences returned by the
    > publisher, not the number of sequences processed locally. This can
    > lead to two issues:
    >
    > 1) Repeated syncing of sequences:
    > If some sequences are missing on the publisher, curr_seq will reflect
    > fewer items than expected, and subsequent batches may reprocess
    > already-synced sequences. Because next batch will use curr_seq to get
    > values from the list as -
    >
    >   seqinfo = (LogicalRepSequenceInfo *)
    > lfirst(list_nth_cell(remotesequences, curr_seq + i));
    >
    > Example:
    > For 110 sequences(s1 to s110), if 5 (s1 to s5) are missing on the
    > publisher in the first batch, curr_seq = 95. In the next cycle, we
    > resync s95 to s99.
    > ~~~~
    >
    > 2) Risk of sequencesync worker getting stuck in infinite loop
    >
    > Consider a case where remotesequences has 10 sequences (s1–s10) need
    > syncing, and concurrently s9, s10 are deleted on the publisher.
    >
    > Cycle 1:
    > Publisher returns s1–s8. So curr_seq = 8.
    >
    > Cycle 2:
    > Publisher query returns zero rows (as s9, s10 no longer exist).
    > curr_seq stays at 8 and never advances.
    >
    > This causes the while (curr_seq < total_seq) loop to run forever.
    > ~~~~
    >
    > I think curr_seq  should be incremented by batch_seq_count just
    > outside the inner while loop.
    >
    
    I faced the similar issue while testing. I think it is due to the
    code-logic issue pointed out by Nisha above.
    
    Test-scenario:
    --Created 250 sequences on both pub and sub.
    --There were 10 sequences mismatched.
    --Sequence replication worked as expected. Logs look better now:
    
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - total unsynchronized: 250; batch #1 = 100 attempted, 97
    succeeded, 3 mismatched
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - total unsynchronized: 250; batch #2 = 100 attempted, 95
    succeeded, 5 mismatched
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - total unsynchronized: 250; batch #3 = 50 attempted, 48
    succeeded, 2 mismatched
    
    --Then I corrected a few and deleted 1 on pub, and the sequence sync
    worker went into an infinite loop after that.
    
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - total unsynchronized: 10; batch #1004 = 1 attempted, 0
    succeeded, 0 mismatched
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - total unsynchronized: 10; batch #1005 = 1 attempted, 0
    succeeded, 0 mismatched
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - total unsynchronized: 10; batch #1006 = 1 attempted, 0
    succeeded, 0 mismatched
    
    
    thanks
    Shveta
    
    
    
    
  224. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-05-20T05:43:04Z

    > Test-scenario:
    > --Created 250 sequences on both pub and sub.
    > --There were 10 sequences mismatched.
    > --Sequence replication worked as expected. Logs look better now:
    >
    > LOG:  Logical replication sequence synchronization for subscription
    > "sub1" - total unsynchronized: 250; batch #1 = 100 attempted, 97
    > succeeded, 3 mismatched
    > LOG:  Logical replication sequence synchronization for subscription
    > "sub1" - total unsynchronized: 250; batch #2 = 100 attempted, 95
    > succeeded, 5 mismatched
    > LOG:  Logical replication sequence synchronization for subscription
    > "sub1" - total unsynchronized: 250; batch #3 = 50 attempted, 48
    > succeeded, 2 mismatched
    >
    
    When there are many batches required, it seems a bit strange to repeat
    the same "total unsynchronized" over and over.
    
    Would it be better to show the total number once, and thereafter show
    the number of sequences remaining to be processed as they tick down?
    
    e.g.
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - total unsynchronized = 250
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - batch #1 = 100 attempted, 97 succeeded, 3 mismatched, 150
    remaining
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - batch #2 = 100 attempted, 95 succeeded, 5 mismatched, 50
    remaining
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - batch #3 = 50 attempted, 48 succeeded, 2 mismatched, 0
    remaining
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  225. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-05-20T09:05:40Z

    On Tue, May 20, 2025 at 8:35 AM Nisha Moond <nisha.moond412@gmail.com> wrote:
    >
    > >
    > > Thanks for the comments, these are handled in the attached v20250516
    > > version patch.
    > >
    >
    > Thanks for the patches. Here are my review comments -
    >
    > Patch-0004: src/backend/replication/logical/sequencesync.c
    >
    
    Hi,
    
    Currently, the behavior of the internal query used to fetch sequence
    info from the pub is inconsistent and potentially misleading.
    
    case1: If a single non-existent sequence is passed (e.g.,  VALUES
    ('public','n10')), the query throws an ERROR, so we get error on sub -
      ERROR:  could not receive list of sequence information from the
    publisher: ERROR:  sequence "public.n10" does not exist
    
    case2: If multiple non-existent sequences are passed (e.g., VALUES
    ('public','n8'),('public','n9')), it silently returns zero rows,
    resulting only in a LOG message instead of an error.
      LOG:  Logical replication sequence synchronization for subscription
    "subs" - total unsynchronized: 2; batch #1 = 2 attempted, 0 succeeded,
    0 mismatched
    
    IMO, This inconsistency can be confusing for users. I think we should
    make the behavior uniform. Either -
     (a) Raise an error if any/all of the requested sequences are missing
    on the publisher, or
     (b) Instead of raising an error, emit a LOG(as is done in case2) and
    maybe include the count of missing sequences too.
    
    I'm fine with either option.
    
    --
    Thanks,
    Nisha
    
    
    
    
  226. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-05-21T10:41:22Z

    On Tue, May 20, 2025 at 11:13 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > > Test-scenario:
    > > --Created 250 sequences on both pub and sub.
    > > --There were 10 sequences mismatched.
    > > --Sequence replication worked as expected. Logs look better now:
    > >
    > > LOG:  Logical replication sequence synchronization for subscription
    > > "sub1" - total unsynchronized: 250; batch #1 = 100 attempted, 97
    > > succeeded, 3 mismatched
    > > LOG:  Logical replication sequence synchronization for subscription
    > > "sub1" - total unsynchronized: 250; batch #2 = 100 attempted, 95
    > > succeeded, 5 mismatched
    > > LOG:  Logical replication sequence synchronization for subscription
    > > "sub1" - total unsynchronized: 250; batch #3 = 50 attempted, 48
    > > succeeded, 2 mismatched
    > >
    >
    > When there are many batches required, it seems a bit strange to repeat
    > the same "total unsynchronized" over and over.
    >
    > Would it be better to show the total number once, and thereafter show
    > the number of sequences remaining to be processed as they tick down?
    >
    > e.g.
    > LOG:  Logical replication sequence synchronization for subscription
    > "sub1" - total unsynchronized = 250
    > LOG:  Logical replication sequence synchronization for subscription
    > "sub1" - batch #1 = 100 attempted, 97 succeeded, 3 mismatched, 150
    > remaining
    > LOG:  Logical replication sequence synchronization for subscription
    > "sub1" - batch #2 = 100 attempted, 95 succeeded, 5 mismatched, 50
    > remaining
    > LOG:  Logical replication sequence synchronization for subscription
    > "sub1" - batch #3 = 50 attempted, 48 succeeded, 2 mismatched, 0
    > remaining
    
    +1 on log change suggestions.
    
    Please find few more comments:
    
    1)
    Temporary sequences will not be replicated, shall we mention this in
    doc under '29.7. Replicating Sequences'?
    
    2)
    CREATE publication pub1 for all sequences  WITH (publish = 'insert,
    update, truncate');
    
    I think it does not make sense to give 'publish' as above (or
    publish_via_partition_root) for 'all sequences' publication. Shall we
    display a WARNING that such will be ignored for 'all sequences' and
    let the create-publication go ahead? Thoughts? Also the doc for
    publish* option in the CREATE-PUBLICATION page needs to specify that
    these options are not-applicable for ALL SEQUENCES publication.
    
    3)
    It will be good to move create_publication.sgml as well to the last
    patch where all other doc changes are present. I was trying to find
    this change in the last patch but ultimately found it in pacth002.
    
    4)
    Currently the log is:
    
    ------
    LOG:  logical replication sequence synchronization worker for
    subscription "sub1" has started
    LOG:  Logical replication sequence synchronization for subscription
    "sub1" - total unsynchronized: 1; batch #1 = 1 attempted, 0 succeeded,
    1 mismatched
    WARNING:  parameters differ for the remote and local sequences
    ("public.myseq34") for subscription "sub1"
    HINT:  Alter/Re-create local sequences to have the same parameters as
    the remote sequences.
    WARNING:  sequence synchronization worker failed: one or more
    sequences have mismatched parameters between the publisher and
    subscriber
    LOG:  logical replication sequence synchronization worker for
    subscription "sub1" has finished
    -----
    
    Do we need both?
    --WARNING:  sequence synchronization worker failed.
    --LOG:  logical replication sequence synchronization worker for
    subscription "sub1" has finished
    
    This WARNING repeats previously stated information. I feel we can get
    rid of it, unless there is a chance of some new error which we are
    trying to display in this WARNING other than mismatched seq error?
    
    thanks
    Shveta
    
    
    
    
  227. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-21T17:34:57Z

    On Tue, 20 May 2025 at 08:35, Nisha Moond <nisha.moond412@gmail.com> wrote:
    >
    > >
    > > Thanks for the comments, these are handled in the attached v20250516
    > > version patch.
    > >
    >
    > Thanks for the patches. Here are my review comments -
    >
    > Patch-0004: src/backend/replication/logical/sequencesync.c
    >
    > The sequence count logic using curr_seq in copy_sequences() seems buggy.
    > Currently, curr_seq is incremented based on the number of tuples
    > received from the publisher inside the inner while loop.
    > This means it's counting the number of sequences returned by the
    > publisher, not the number of sequences processed locally. This can
    > lead to two issues:
    >
    > 1) Repeated syncing of sequences:
    > If some sequences are missing on the publisher, curr_seq will reflect
    > fewer items than expected, and subsequent batches may reprocess
    > already-synced sequences. Because next batch will use curr_seq to get
    > values from the list as -
    >
    >   seqinfo = (LogicalRepSequenceInfo *)
    > lfirst(list_nth_cell(remotesequences, curr_seq + i));
    >
    > Example:
    > For 110 sequences(s1 to s110), if 5 (s1 to s5) are missing on the
    > publisher in the first batch, curr_seq = 95. In the next cycle, we
    > resync s95 to s99.
    > ~~~~
    >
    > 2) Risk of sequencesync worker getting stuck in infinite loop
    >
    > Consider a case where remotesequences has 10 sequences (s1–s10) need
    > syncing, and concurrently s9, s10 are deleted on the publisher.
    >
    > Cycle 1:
    > Publisher returns s1–s8. So curr_seq = 8.
    >
    > Cycle 2:
    > Publisher query returns zero rows (as s9, s10 no longer exist).
    > curr_seq stays at 8 and never advances.
    >
    > This causes the while (curr_seq < total_seq) loop to run forever.
    
    These are handled in the attached v20250521 version patch.
    Also the issue reported at [1] is handled in the attached patch.
    
    [1] - https://www.postgresql.org/message-id/CAHut%2BPstucunJLQn8C%3DbewmYdoSQStBcEJgG2bkZJUZnTowhFQ%40mail.gmail.com
    
    Regards,
    Vignesh
    
  228. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-21T17:36:54Z

    On Tue, 20 May 2025 at 09:54, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Tue, May 20, 2025 at 8:35 AM Nisha Moond <nisha.moond412@gmail.com> wrote:
    > >
    > > >
    > > > Thanks for the comments, these are handled in the attached v20250516
    > > > version patch.
    > > >
    > >
    > > Thanks for the patches. Here are my review comments -
    > >
    > > Patch-0004: src/backend/replication/logical/sequencesync.c
    > >
    > > The sequence count logic using curr_seq in copy_sequences() seems buggy.
    > > Currently, curr_seq is incremented based on the number of tuples
    > > received from the publisher inside the inner while loop.
    > > This means it's counting the number of sequences returned by the
    > > publisher, not the number of sequences processed locally. This can
    > > lead to two issues:
    > >
    > > 1) Repeated syncing of sequences:
    > > If some sequences are missing on the publisher, curr_seq will reflect
    > > fewer items than expected, and subsequent batches may reprocess
    > > already-synced sequences. Because next batch will use curr_seq to get
    > > values from the list as -
    > >
    > >   seqinfo = (LogicalRepSequenceInfo *)
    > > lfirst(list_nth_cell(remotesequences, curr_seq + i));
    > >
    > > Example:
    > > For 110 sequences(s1 to s110), if 5 (s1 to s5) are missing on the
    > > publisher in the first batch, curr_seq = 95. In the next cycle, we
    > > resync s95 to s99.
    > > ~~~~
    > >
    > > 2) Risk of sequencesync worker getting stuck in infinite loop
    > >
    > > Consider a case where remotesequences has 10 sequences (s1–s10) need
    > > syncing, and concurrently s9, s10 are deleted on the publisher.
    > >
    > > Cycle 1:
    > > Publisher returns s1–s8. So curr_seq = 8.
    > >
    > > Cycle 2:
    > > Publisher query returns zero rows (as s9, s10 no longer exist).
    > > curr_seq stays at 8 and never advances.
    > >
    > > This causes the while (curr_seq < total_seq) loop to run forever.
    > > ~~~~
    > >
    > > I think curr_seq  should be incremented by batch_seq_count just
    > > outside the inner while loop.
    > >
    >
    > I faced the similar issue while testing. I think it is due to the
    > code-logic issue pointed out by Nisha above.
    
    Yes, it is the same issue, this has been fixed in the v20250521
    version posted at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm2ZgyYbowqZJfpkpRV_tev5o-rqpkLDkp496ku15Tdsqw%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  229. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-22T17:12:02Z

    On Wed, 21 May 2025 at 16:11, shveta malik <shveta.malik@gmail.com> wrote:
    > Please find few more comments:
    >
    > 1)
    > Temporary sequences will not be replicated, shall we mention this in
    > doc under '29.7. Replicating Sequences'?
    
    I added it create publication "ALL SEQUENCES" section as similar
    restriction about table is mentioned there
    
    > 2)
    > CREATE publication pub1 for all sequences  WITH (publish = 'insert,
    > update, truncate');
    >
    > I think it does not make sense to give 'publish' as above (or
    > publish_via_partition_root) for 'all sequences' publication. Shall we
    > display a WARNING that such will be ignored for 'all sequences' and
    > let the create-publication go ahead? Thoughts? Also the doc for
    > publish* option in the CREATE-PUBLICATION page needs to specify that
    > these options are not-applicable for ALL SEQUENCES publication.
    
    I felt no need to add a warning, just adding to documentation would be enough.
    
    > 3)
    > It will be good to move create_publication.sgml as well to the last
    > patch where all other doc changes are present. I was trying to find
    > this change in the last patch but ultimately found it in pacth002.
    
    Moved
    
    > 4)
    > Currently the log is:
    >
    > ------
    > LOG:  logical replication sequence synchronization worker for
    > subscription "sub1" has started
    > LOG:  Logical replication sequence synchronization for subscription
    > "sub1" - total unsynchronized: 1; batch #1 = 1 attempted, 0 succeeded,
    > 1 mismatched
    > WARNING:  parameters differ for the remote and local sequences
    > ("public.myseq34") for subscription "sub1"
    > HINT:  Alter/Re-create local sequences to have the same parameters as
    > the remote sequences.
    > WARNING:  sequence synchronization worker failed: one or more
    > sequences have mismatched parameters between the publisher and
    > subscriber
    > LOG:  logical replication sequence synchronization worker for
    > subscription "sub1" has finished
    > -----
    >
    > Do we need both?
    
    Removed it.
    
    The attached v20250522 patch has the changes for the same.
    
    Regards,
    Vignesh
    
  230. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-05-28T15:21:52Z

    On Thu, May 22, 2025 at 10:42 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > The attached v20250522 patch has the changes for the same.
    >
    
    Thank you for the patches, please find comments for patch-0004.
    
    1)
    +/*
    + * report_error_sequences
    + *
    + * Logs a warning listing all sequences that are missing on the publisher,
    + * as well as those with value mismatches relative to the subscriber.
    + */
    +static void
    +report_error_sequences(StringInfo missing_seqs, StringInfo mismatched_seqs)
    
    The function description should be updated to reflect the recent
    changes, as it now raises an error instead of issuing a warning.
    
    2)
    + ereport(ERROR, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("%s", combined_error_msg->data));
    +
    + destroyStringInfo(combined_error_msg);
    +}
    
    I think we can remove destroyStringInfo() as we will never reach here
    in case of error.
    
    3)
    + * we want to avoid keeping this batch transaction open for extended
    + * periods so it iscurrently limited to 100 sequences per batch.
    + */
    
    typo :  iscurrently / is currently
    
    4)
    + HeapTuple tup;
    + Form_pg_sequence seqform;
    + LogicalRepSequenceInfo *seqinfo;
    +
    [...]
    + Assert(seqinfo);
    
    Since there's an assertion for 'seqinfo', it would be safer to
    initialize it to NULL to avoid any unexpected behavior.
    
    6)
    + if (missing_seqs->len || mismatched_seqs->len)
    + report_error_sequences(missing_seqs, mismatched_seqs);
    
    I think it would be helpful to add a comment for this check, perhaps
    something like:
    /*
     * Report an error if any sequences are missing on the remote side
     * or if local sequence parameters don't match with the remote ones.
     */
     Please rephrase if needed.
    ~~~~
    
    --
    Thanks,
    Nisha
    
    
    
    
  231. Re: Logical Replication of sequences

    Ajin Cherian <itsajin@gmail.com> — 2025-05-29T05:59:51Z

    On Fri, May 23, 2025 at 3:12 AM vignesh C <vignesh21@gmail.com> wrote:
    
    >
    >
    > The attached v20250522 patch has the changes for the same.
    >
    > Regards,
    > Vignesh
    >
    
    Some review comments for patch 0001:
    1. In src/backend/commands/sequence.c
    in pg_sequence_state()
    + /* open and lock sequence */
    + init_sequence(seq_relid, &elm, &seqrel);
    +
    + if (pg_class_aclcheck(elm->relid, GetUserId(),
    +  ACL_SELECT | ACL_USAGE) != ACLCHECK_OK)
    + ereport(ERROR,
    + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    + errmsg("permission denied for sequence %s",
    +   RelationGetRelationName(seqrel)));
    +
    
    How about using aclcheck_error for this, which also supports error messages
    for specific access errors. Most other objects seem to be using this.
    if (aclresult != ACLCHECK_OK)
    aclcheck_error(aclresult, get_relkind_objtype(seqrel->relkind),
      RelationGetRelationName(seqrel));
    
    2. in function pg_sequence_state()
    +
    + UnlockReleaseBuffer(buf);
    + relation_close(seqrel, NoLock);
    
    Ideally the corresponding close for init_sequence is sequence_close()
    rather than relation_close()
    
    I will post comments for the other patches as well.
    
    regards,
    Ajin Cherian
    Fujitsu Australia
    
  232. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-29T14:39:13Z

    On Wed, 28 May 2025 at 20:52, Nisha Moond <nisha.moond412@gmail.com> wrote:
    >
    > On Thu, May 22, 2025 at 10:42 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > >
    > > The attached v20250522 patch has the changes for the same.
    > >
    >
    > Thank you for the patches, please find comments for patch-0004.
    >
    > 1)
    > +/*
    > + * report_error_sequences
    > + *
    > + * Logs a warning listing all sequences that are missing on the publisher,
    > + * as well as those with value mismatches relative to the subscriber.
    > + */
    > +static void
    > +report_error_sequences(StringInfo missing_seqs, StringInfo mismatched_seqs)
    >
    > The function description should be updated to reflect the recent
    > changes, as it now raises an error instead of issuing a warning.
    >
    > 2)
    > + ereport(ERROR, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("%s", combined_error_msg->data));
    > +
    > + destroyStringInfo(combined_error_msg);
    > +}
    >
    > I think we can remove destroyStringInfo() as we will never reach here
    > in case of error.
    >
    > 3)
    > + * we want to avoid keeping this batch transaction open for extended
    > + * periods so it iscurrently limited to 100 sequences per batch.
    > + */
    >
    > typo :  iscurrently / is currently
    >
    > 4)
    > + HeapTuple tup;
    > + Form_pg_sequence seqform;
    > + LogicalRepSequenceInfo *seqinfo;
    > +
    > [...]
    > + Assert(seqinfo);
    >
    > Since there's an assertion for 'seqinfo', it would be safer to
    > initialize it to NULL to avoid any unexpected behavior.
    >
    > 6)
    > + if (missing_seqs->len || mismatched_seqs->len)
    > + report_error_sequences(missing_seqs, mismatched_seqs);
    >
    > I think it would be helpful to add a comment for this check, perhaps
    > something like:
    > /*
    >  * Report an error if any sequences are missing on the remote side
    >  * or if local sequence parameters don't match with the remote ones.
    >  */
    >  Please rephrase if needed.
    
    These comments are handled in the attached v2025029 version patch.
    
    Regards,
    Vignesh
    
  233. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-05-29T14:41:15Z

    >
    > Some review comments for patch 0001:
    > 1. In src/backend/commands/sequence.c
    > in pg_sequence_state()
    > + /* open and lock sequence */
    > + init_sequence(seq_relid, &elm, &seqrel);
    > +
    > + if (pg_class_aclcheck(elm->relid, GetUserId(),
    > +  ACL_SELECT | ACL_USAGE) != ACLCHECK_OK)
    > + ereport(ERROR,
    > + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    > + errmsg("permission denied for sequence %s",
    > +   RelationGetRelationName(seqrel)));
    > +
    >
    > How about using aclcheck_error for this, which also supports error messages for specific access errors. Most other objects seem to be using this.
    > if (aclresult != ACLCHECK_OK)
    > aclcheck_error(aclresult, get_relkind_objtype(seqrel->relkind),
    >   RelationGetRelationName(seqrel));
    
    I felt this is ok in this case as it is used similarly in
    nextval_internal, currval_oid, lastval, do_setval and
    pg_sequence_parameters also
    
    > 2. in function pg_sequence_state()
    > +
    > + UnlockReleaseBuffer(buf);
    > + relation_close(seqrel, NoLock);
    >
    > Ideally the corresponding close for init_sequence is sequence_close() rather than relation_close()
    
    Fixed
    
    The comment for the same is handled in the v2025029 version patch
    attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm0ssEaHW8by5kd1%3DwE7LPMhhBiV6971JbFWsY6Qwp7NMw%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  234. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-06-02T09:24:34Z

    On Thu, May 29, 2025 at 8:09 PM vignesh C <vignesh21@gmail.com> wrote:
    > These comments are handled in the attached v2025029 version patch.
    >
    
    Thanks for the patches. I am still reviewing but please find few comments:
    
    1)
         <para>
          Only persistent sequences are included in the publication. Temporary
          sequences are excluded from the publication.
         </para>
    
    We shall mention UNLOGGED sequences as well along with TEMP sequences.
    
    2)
    Why do we have GetAllSequencesPublicationRelations() in patch002? It
    is used only in patch004. Same thing with is_publishable_class()
    change.
    
    3)
    process_syncing_tables_for_sync() is renamed to ProcessSyncingTablesForSync()
    process_syncing_tables_for_apply() is renamed to ProcessSyncingTablesForApply()
    process_syncing_tables() is renamed to SyncProcessRelations()
    
    Why have we named it SyncProcessRelations and not
    ProcessSyncingRelations? Is it because we want to start a name with
    'Sync' in order to have file name initials? But do not see other files
    following it. IMO, ProcessSyncingTables looks more familiar and apt
    over SyncProcessRelations. Same with 'SyncFinishWorker'.
    FinishSyncWorker instead looks better. Thoughts?
    
    
    4)
    postgres=# CREATE publication pub1 for sequences;
    ERROR:  invalid publication object list
    LINE 1: CREATE publication pub1 for sequences;
                                        ^
    DETAIL:  One of TABLE or TABLES IN SCHEMA must be specified before a
    standalone table or schema name.
    
    Do you think we shall mention sequence specific info as well in DETAIL now?
    
    thanks
    Shveta
    
    
    
    
  235. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-06-03T11:41:13Z

    On Thu, May 29, 2025 at 8:09 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > These comments are handled in the attached v2025029 version patch.
    >
    
    1. The current syntax to publish sequences is:
    CREATE PUBLICATION pub1 FOR ALL TABLES, ALL SEQUENCES;
    
    The other alternative could be:
    CREATE PUBLICATION pub1 FOR ALL TABLES, SEQUENCES;
    
    I think the syntax proposed by the patch is better because of the
    following reasons: (a) The use of ALL before both objects makes the
    intent explicit and symmetrical. (b) As we are planning to support FOR
    TABLE t1, SEQUENCE s1, so ALL SEQUENCES fit naturally as a counterpart
    to ALL TABLES.
    
    Please let me know if anyone thinks otherwise.
    
    2. The 0001 patch has the following commit message:
    "Introduce pg_sequence_state function for enhanced sequence
    management. This patch introduces a new function, 'pg_sequence_state',
    which
    allows retrieval of sequence values, including the associated LSN."
    
    It doesn't mention the use of introducing this new function.
    
    Following comments on the 0004 patch
    3.
     List *
    -GetSubscriptionRelations(Oid subid, bool not_ready)
    +GetSubscriptionRelations(Oid subid, bool get_tables, bool get_sequences,
    + bool all_states)
    
    What is the need to change the not_ready flag? Can't not_ready serve the need?
    
    4.
    +void
    +SetSequence(Oid relid, int64 next, bool is_called, int64 log_cnt)
    
    The argument order seems odd. Isn't it better to keep 'int64 log_cnt'
    next to 'int64 next' and then a bool at the end?
    
    5.
    + /*
    + * XXX: If the subscription is for a sequence-only publication, creating
    + * this origin is unnecessary. It can be created later during the ALTER
    + * SUBSCRIPTION ... REFRESH command, if the publication is updated to
    + * include tables.
    + */
    
    Can you explain in comments why creating an origin is unnecessary? The
    same is true for a similar comment on slots. If the patch has
    explained it somewhere else, then mention a reference to that.
    
    6. ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES
    
    Can we move the implementation of the above command to a separate
    patch? This is to make 0004 shorter and easier to review.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  236. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-06-10T03:15:38Z

    On Tue, Jun 3, 2025 at 5:11 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, May 29, 2025 at 8:09 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > These comments are handled in the attached v2025029 version patch.
    > >
    >
    > 1. The current syntax to publish sequences is:
    > CREATE PUBLICATION pub1 FOR ALL TABLES, ALL SEQUENCES;
    >
    > The other alternative could be:
    > CREATE PUBLICATION pub1 FOR ALL TABLES, SEQUENCES;
    >
    > I think the syntax proposed by the patch is better because of the
    > following reasons: (a) The use of ALL before both objects makes the
    > intent explicit and symmetrical. (b) As we are planning to support FOR
    > TABLE t1, SEQUENCE s1, so ALL SEQUENCES fit naturally as a counterpart
    > to ALL TABLES.
    >
    > Please let me know if anyone thinks otherwise.
    
    +1
    
    >
    > 6. ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES
    >
    > Can we move the implementation of the above command to a separate
    > patch? This is to make 0004 shorter and easier to review.
    >
    
    Splitted patch-0004 as follows:
     - patch-0004: Implements the new REFRESH PUBLICATION SEQUENCES command.
     - patch-0005: Implementation of the sequencesync worker.
    
    Attached patches address feedback from Amit [1] and Shveta [2].
    
    [1] https://www.postgresql.org/message-id/CAJpy0uD00JCsgDxL3YjdPQFSnV4mv4D9XPZV_9%3DaMNDLao7SQQ%40mail.gmail.com
    [2] https://www.postgresql.org/message-id/CAA4eK1%2B6L%2BAoGS3LHdnYnCE%3DnRHergSQyhyO7Y%3D-sOp7isGVMw%40mail.gmail.com
    
    --
    Thanks,
    Nisha
    
  237. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-06-19T05:56:11Z

    Hi,
    
    Here are my review comments for v20250610 patches:
    
    Patch-0005:sequencesync.c
    
    1) report_error_sequences()
    
    In case there are both missing and mismatched sequences, the ERROR
    message logged is -
    
    ```
    2025-05-28 14:22:19.898 IST [392259] ERROR:  logical replication
    sequence synchronization failed for subscription "subs": sequences
    ("public"."n84") are missing on the publisher. Additionally,
    parameters differ for the remote and local sequences ("public.n1")
    ```
    
    I feel this error message is quite long. Would it be possible to split
    it into ERROR and DETAIL? Also, if feasible, we could consider
    including a HINT, as was done in previous versions.
    
    I explored a few possible ways to log this error with a hint. Attached
    top-up patch has the suggestion implemented. Please see if it seems
    okay to consider.
    ~~~
    
    2) copy_sequences():
    + /* Retrieve the sequence object fetched from the publisher */
    + for (int i = 0; i < batch_size; i++)
    + {
    + LogicalRepSequenceInfo *sequence_info =
    lfirst(list_nth_cell(remotesequences, current_index + i));
    +
    + if (!strcmp(sequence_info->nspname, nspname) &&
    + !strcmp(sequence_info->seqname, seqname))
    + seqinfo = sequence_info;
    + }
    
    The current logic performs a search through the local sequence list
    for each sequence fetched from the publisher, repeating the traverse
    of 100(batch size) length of the list per sequence, which may impact
    performance.
    
    To improve efficiency, we can optimize it by sorting the local list
    and traverses it only once for matching. Kindly review the
    implementation in the attached top-up patch and consider merging it if
    it looks good to you.
    ~~~
    
    3) copy_sequences():
    + if (message_level_is_interesting(DEBUG1))
    + ereport(DEBUG1,
    + errmsg_internal("logical replication synchronization for
    subscription \"%s\", sequence \"%s\" has finished",
    + MySubscription->name,
    + seqinfo->seqname));
    +
    + batch_succeeded_count++;
    + }
    
    The current debug log might be a bit confusing when sequences with the
    same name exist in different schemas. To improve clarity, we could
    include the schema name in the message, e.g.,
    " ... sequence "schema"."sequence" has finished".
    ~~~~
    
    Few minor comments in doc - Patch-0006 : logical-replication.sgml
    
    4)
    +  <para>
    +   To replicate sequences from a publisher to a subscriber, first publish them
    +   using <link linkend="sql-createpublication-params-for-all-sequences">
    +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link>.
    +  </para>
    
    I think it would be better to use "To synchronize" instead of "To
    replicate" here, to maintain consistency and avoid confusion between
    replication and synchronization.
    
    5)
    +   <para>
    +    Update the sequences at the publisher side few times.
    +<programlisting>
    
    /side few /side a few /
    
    6) Can avoid using multiple "or" in the sentences below:
    
    6a)
    -   a change set or replication set.  Each publication exists in only
    one database.
    +   generated from a table or a group of tables or the current state of all
    +   sequences, and might also be described as a change set or replication set
    
    / table or a group of tables/ table, a group of tables/
    
    6b)
    +   Publications may currently only contain tables or sequences. Objects must be
    +   added explicitly, except when a publication is created using
    +   <literal>FOR TABLES IN SCHEMA</literal>, or <literal>FOR ALL
    TABLES</literal>,
    +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    
    / IN SCHEMA</literal>, or <literal>FOR ALL TABLES/ IN
    SCHEMA</literal>, <literal>FOR ALL TABLES
    
    --
    Thanks,
    Nisha
    
  238. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-06-22T02:35:20Z

    On Thu, 19 Jun 2025 at 11:26, Nisha Moond <nisha.moond412@gmail.com> wrote:
    >
    > Hi,
    >
    > Here are my review comments for v20250610 patches:
    >
    > Patch-0005:sequencesync.c
    >
    > 1) report_error_sequences()
    >
    > In case there are both missing and mismatched sequences, the ERROR
    > message logged is -
    >
    > ```
    > 2025-05-28 14:22:19.898 IST [392259] ERROR:  logical replication
    > sequence synchronization failed for subscription "subs": sequences
    > ("public"."n84") are missing on the publisher. Additionally,
    > parameters differ for the remote and local sequences ("public.n1")
    > ```
    >
    > I feel this error message is quite long. Would it be possible to split
    > it into ERROR and DETAIL? Also, if feasible, we could consider
    > including a HINT, as was done in previous versions.
    >
    > I explored a few possible ways to log this error with a hint. Attached
    > top-up patch has the suggestion implemented. Please see if it seems
    > okay to consider.
    
    This looks good, merged it.
    > ~~~
    >
    > 2) copy_sequences():
    > + /* Retrieve the sequence object fetched from the publisher */
    > + for (int i = 0; i < batch_size; i++)
    > + {
    > + LogicalRepSequenceInfo *sequence_info =
    > lfirst(list_nth_cell(remotesequences, current_index + i));
    > +
    > + if (!strcmp(sequence_info->nspname, nspname) &&
    > + !strcmp(sequence_info->seqname, seqname))
    > + seqinfo = sequence_info;
    > + }
    >
    > The current logic performs a search through the local sequence list
    > for each sequence fetched from the publisher, repeating the traverse
    > of 100(batch size) length of the list per sequence, which may impact
    > performance.
    >
    > To improve efficiency, we can optimize it by sorting the local list
    > and traverses it only once for matching. Kindly review the
    > implementation in the attached top-up patch and consider merging it if
    > it looks good to you.
    
    Looks good, merged it.
    
    > ~~~
    >
    > 3) copy_sequences():
    > + if (message_level_is_interesting(DEBUG1))
    > + ereport(DEBUG1,
    > + errmsg_internal("logical replication synchronization for
    > subscription \"%s\", sequence \"%s\" has finished",
    > + MySubscription->name,
    > + seqinfo->seqname));
    > +
    > + batch_succeeded_count++;
    > + }
    >
    > The current debug log might be a bit confusing when sequences with the
    > same name exist in different schemas. To improve clarity, we could
    > include the schema name in the message, e.g.,
    > " ... sequence "schema"."sequence" has finished".
    
    Modified
    
    > ~~~~
    >
    > Few minor comments in doc - Patch-0006 : logical-replication.sgml
    >
    > 4)
    > +  <para>
    > +   To replicate sequences from a publisher to a subscriber, first publish them
    > +   using <link linkend="sql-createpublication-params-for-all-sequences">
    > +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link>.
    > +  </para>
    >
    > I think it would be better to use "To synchronize" instead of "To
    > replicate" here, to maintain consistency and avoid confusion between
    > replication and synchronization.
    
    Modified
    
    > 5)
    > +   <para>
    > +    Update the sequences at the publisher side few times.
    > +<programlisting>
    >
    > /side few /side a few /
    >
    > 6) Can avoid using multiple "or" in the sentences below:
    >
    > 6a)
    > -   a change set or replication set.  Each publication exists in only
    > one database.
    > +   generated from a table or a group of tables or the current state of all
    > +   sequences, and might also be described as a change set or replication set
    >
    > / table or a group of tables/ table, a group of tables/
    
    Modified
    
    > 6b)
    > +   Publications may currently only contain tables or sequences. Objects must be
    > +   added explicitly, except when a publication is created using
    > +   <literal>FOR TABLES IN SCHEMA</literal>, or <literal>FOR ALL
    > TABLES</literal>,
    > +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    >
    > / IN SCHEMA</literal>, or <literal>FOR ALL TABLES/ IN
    > SCHEMA</literal>, <literal>FOR ALL TABLES
    
    Modified
    
    Thanks for the comment, the attached v20250622 version patch has the
    changes for the same.
    
    Regards,
    Vignesh
    
  239. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-06-24T05:07:00Z

    >
    > Thanks for the comment, the attached v20250622 version patch has the
    > changes for the same.
    >
    
    Thanks for the patches, I am not done with review yet, but please find
    the feedback so far:
    
    
    1)
    + if (!OidIsValid(seq_relid))
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("sequence \"%s.%s\" does not exist",
    +    schema_name, sequence_name));
    
    ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE might not be a correct error
    code here. Shall we have ERRCODE_UNDEFINED_OBJECT? Thoughts?
    
    
    2)
    tab-complete here shows correctly:
    
    postgres=# CREATE PUBLICATION pub6 FOR ALL
    SEQUENCES  TABLES
    
    But tab-complete for these 2 commands does not show anything:
    
    postgres=# CREATE PUBLICATION pub6 FOR ALL TABLES,
    postgres=# CREATE PUBLICATION pub6 FOR ALL SEQUENCES,
    
    We shall specify SEQUENCES/TABLES in above commands. IIUC, we do not
    support any other combination like (table <name>, tables in schema
    <name>) once we get ALL clause in command. So it is safe to display
    tab-complete as either TABLES or SEQUENECS in above.
    
    3)
    postgres=#  CREATE publication pub1 for sequences;
    ERROR:  invalid publication object list
    LINE 1: CREATE publication pub1 for sequences;
                                     ^
    DETAIL:  One of TABLE, TABLES IN SCHEMA or ALL SEQUENCES must be
    specified before a standalone table or schema name.
    
    
    This message is not correct as we can not have ALL SEQUENCES *before*
    a standalone table or schema name. The problem is that gram.y is
    taking *sequences* as a table or schema name. I noticed that it does
    same with *tables* as well:
    
    postgres=#  CREATE publication pub1 for tables;
    ERROR:  invalid publication object list
    LINE 1: CREATE publication pub1 for tables;
                                      ^
    DETAIL:  One of TABLE, TABLES IN SCHEMA or ALL SEQUENCES must be
    specified before a standalone table or schema name.
    
    
    But since gram.y here can not identify an in-between missing keyword
    *all*, thus it is considering it (tables/sequenecs) as a literal/name
    instead of keyword. We can revert back to old message in such a case.
    I am unable to think of a good solution here.
    
    
    4)
    I think the error here is wrong as we are not trying to specify
    multiple all-tables entries.
    
    postgres=# CREATE PUBLICATION pub6 for all tables, tables in schema public;
    ERROR:  invalid publication object list
    LINE 1: CREATE PUBLICATION pub6 for all tables, tables in schema pub...
    
                                                    ^
    DETAIL:  ALL TABLES can be specified only once.
    
    
    5)
    The log messages still has some scope of improvement:
    
    2025-06-24 08:52:17.988 IST [110359] LOG:  logical replication
    sequence synchronization worker for subscription "sub1" has started
    2025-06-24 08:52:18.029 IST [110359] LOG:  logical replication
    sequence synchronization for subscription "sub1" - total
    unsynchronized: 3
    2025-06-24 08:52:18.090 IST [110359] LOG:  logical replication
    sequence synchronization for subscription "sub1" - batch #1 = 3
    attempted, 0 succeeded, 2 mismatched, 1 missing
    2025-06-24 08:52:18.091 IST [110359] ERROR:  logical replication
    sequence synchronization failed for subscription "sub1"
    2025-06-24 08:52:18.091 IST [110359] DETAIL:  Sequences
    ("public.myseq100") are missing on the publisher. Additionally,
    parameters differ for the remote and local sequences
    ("public.myseq101", "public.myseq102").
    2025-06-24 08:52:18.091 IST [110359] HINT:  Use ALTER SUBSCRIPTION ...
    REFRESH PUBLICATION or use ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES. Alter or re-create local sequences to have the same
    parameters as the remote sequences
    
    
    a)
    Sequences ("public.myseq100") are missing on the publisher.
    Additionally, parameters differ for the remote and local sequences
    ("public.myseq101", "public.myseq102").
    
    Shall we change this to:
    missing sequence(s) on publisher: ("public.myseq100"); mismatched
    sequences(s) on subscriber: ("public.myseq101", "public.myseq102")
    
    It will then be similar to the previous log pattern ( 3 attempted, 0
    succeeded etc) instead of being more verbal. Thoughts?
    
    
    b)
    Hints are a little odd. First line of hint is just saying to use
    'ALTER SUBSCRIPTION' without giving any purpose. While the second line
    of hint is giving the purpose of alter-sequences.
    
    Shall we have?
    For missing sequences, use ALTER SUBSCRIPTION with either REFRESH
    PUBLICATION or REFRESH PUBLICATION SEQUENCES
    For mismatched sequences, alter or re-create local sequences to have
    matching parameters as publishers.
    
    Thoughts?
    
    6)
    postgres=# create publication pub1 for table tab1, all sequences;
    ERROR:  syntax error at or near "all"
    LINE 1: create publication pub1 for table tab1, all sequences;
    
    We can mention in commit msg that this combination is also not
    supported or what all combinations are supported. Currently it is not
    clear f
    
    thanks
    Shveta
    
    
    
    
  240. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-06-24T09:37:28Z

    On Sun, Jun 22, 2025 at 8:05 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > Thanks for the comment, the attached v20250622 version patch has the
    > changes for the same.
    >
    
    Thanks for the patches, please find my review comments for patches 001 and 002:
    
    1) patch-001 :pg_sequence_state()
    
    + /* open and lock sequence */
    + init_sequence(seq_relid, &elm, &seqrel);
    
    / open/ Open
    ~~~
    
    patch-0002:
    
    2)
    - /* FOR ALL TABLES requires superuser */
    - if (stmt->for_all_tables && !superuser())
    - ereport(ERROR,
    - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    - errmsg("must be superuser to create FOR ALL TABLES publication")));
    + if (!superuser())
    
    I think we can retain the original comment here with required modification :
      /* FOR ALL TABLES and FOR ALL SEQUENCES requires superuser */
    ~~~
    
    3) ALL TABLES vs ALL SEQUENCES
    
    For the command:
      CREATE PUBLICATION FOR ALL TABLES, [...]
     - only "SEQUENCES" is allowed after ',', and TABLE or TABLES IN
    SCHEMA are not allowed. Which aligns with the fact that "all tables"
    is inclusive of "FOR TABLE" and "FOR TABLES IN SCHEMA".
    Therefore, adding and dropping of tables from a "ALL TABLES"
    publication is also not allowed. e.g.,
    
    ```
    postgres=# alter publication test add table t1;
    ERROR:  publication "test" is defined as FOR ALL TABLES
    DETAIL:  Tables cannot be added to or dropped from FOR ALL TABLES publications.
    
    postgres=# alter publication test add tables in schema public;
    ERROR:  publication "test" is defined as FOR ALL TABLES
    DETAIL:  Schemas cannot be added to or dropped from FOR ALL TABLES publications.
    ```
    
    However, for ALL SEQUENCES, the behavior seems inconsistent. CREATE
    PUBLICATION doesn’t allow adding TABLE or TABLES IN SCHEMA along with
    ALL SEQUENCES, but ALTER PUBLICATION does.
    e.g., for a all sequence publication 'pubs', below succeeds :
    postgres=# alter publication pubs add table t1;
    ALTER PUBLICATION
    
    Is this expected?
    If adding tables is allowed using ALTER PUBLICATION, perhaps it should
    also be permitted during CREATE PUBLICATION or disallowed in both
    cases. Thoughts?
    ~~~
    
    4) Consider a publication 'pubs' on all sequences and 'n1' is a sequence, now -
    
    postgres=# alter publication pubs drop table n1;
    ERROR:  relation "n1" is not part of the publication
    
    This error message can be misleading, as the relation n1 is part of
    the publication - it's just a sequence, not a table.
    It might be more accurate to add a DETAIL line similar to ADD case:
    
    postgres=# alter publication pubs add table n1;
    ERROR:  cannot add relation "n1" to publication
    DETAIL:  This operation is not supported for sequences.
    ~~~
    
    --
    Thanks.
    Nisha
    
    
    
    
  241. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2025-06-24T13:14:18Z

    On Sun, 22 Jun 2025 at 08:05, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 19 Jun 2025 at 11:26, Nisha Moond <nisha.moond412@gmail.com> wrote:
    > >
    > > Hi,
    > >
    > > Here are my review comments for v20250610 patches:
    > >
    > > Patch-0005:sequencesync.c
    > >
    > > 1) report_error_sequences()
    > >
    > > In case there are both missing and mismatched sequences, the ERROR
    > > message logged is -
    > >
    > > ```
    > > 2025-05-28 14:22:19.898 IST [392259] ERROR:  logical replication
    > > sequence synchronization failed for subscription "subs": sequences
    > > ("public"."n84") are missing on the publisher. Additionally,
    > > parameters differ for the remote and local sequences ("public.n1")
    > > ```
    > >
    > > I feel this error message is quite long. Would it be possible to split
    > > it into ERROR and DETAIL? Also, if feasible, we could consider
    > > including a HINT, as was done in previous versions.
    > >
    > > I explored a few possible ways to log this error with a hint. Attached
    > > top-up patch has the suggestion implemented. Please see if it seems
    > > okay to consider.
    >
    > This looks good, merged it.
    > > ~~~
    > >
    > > 2) copy_sequences():
    > > + /* Retrieve the sequence object fetched from the publisher */
    > > + for (int i = 0; i < batch_size; i++)
    > > + {
    > > + LogicalRepSequenceInfo *sequence_info =
    > > lfirst(list_nth_cell(remotesequences, current_index + i));
    > > +
    > > + if (!strcmp(sequence_info->nspname, nspname) &&
    > > + !strcmp(sequence_info->seqname, seqname))
    > > + seqinfo = sequence_info;
    > > + }
    > >
    > > The current logic performs a search through the local sequence list
    > > for each sequence fetched from the publisher, repeating the traverse
    > > of 100(batch size) length of the list per sequence, which may impact
    > > performance.
    > >
    > > To improve efficiency, we can optimize it by sorting the local list
    > > and traverses it only once for matching. Kindly review the
    > > implementation in the attached top-up patch and consider merging it if
    > > it looks good to you.
    >
    > Looks good, merged it.
    >
    > > ~~~
    > >
    > > 3) copy_sequences():
    > > + if (message_level_is_interesting(DEBUG1))
    > > + ereport(DEBUG1,
    > > + errmsg_internal("logical replication synchronization for
    > > subscription \"%s\", sequence \"%s\" has finished",
    > > + MySubscription->name,
    > > + seqinfo->seqname));
    > > +
    > > + batch_succeeded_count++;
    > > + }
    > >
    > > The current debug log might be a bit confusing when sequences with the
    > > same name exist in different schemas. To improve clarity, we could
    > > include the schema name in the message, e.g.,
    > > " ... sequence "schema"."sequence" has finished".
    >
    > Modified
    >
    > > ~~~~
    > >
    > > Few minor comments in doc - Patch-0006 : logical-replication.sgml
    > >
    > > 4)
    > > +  <para>
    > > +   To replicate sequences from a publisher to a subscriber, first publish them
    > > +   using <link linkend="sql-createpublication-params-for-all-sequences">
    > > +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link>.
    > > +  </para>
    > >
    > > I think it would be better to use "To synchronize" instead of "To
    > > replicate" here, to maintain consistency and avoid confusion between
    > > replication and synchronization.
    >
    > Modified
    >
    > > 5)
    > > +   <para>
    > > +    Update the sequences at the publisher side few times.
    > > +<programlisting>
    > >
    > > /side few /side a few /
    > >
    > > 6) Can avoid using multiple "or" in the sentences below:
    > >
    > > 6a)
    > > -   a change set or replication set.  Each publication exists in only
    > > one database.
    > > +   generated from a table or a group of tables or the current state of all
    > > +   sequences, and might also be described as a change set or replication set
    > >
    > > / table or a group of tables/ table, a group of tables/
    >
    > Modified
    >
    > > 6b)
    > > +   Publications may currently only contain tables or sequences. Objects must be
    > > +   added explicitly, except when a publication is created using
    > > +   <literal>FOR TABLES IN SCHEMA</literal>, or <literal>FOR ALL
    > > TABLES</literal>,
    > > +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    > >
    > > / IN SCHEMA</literal>, or <literal>FOR ALL TABLES/ IN
    > > SCHEMA</literal>, <literal>FOR ALL TABLES
    >
    > Modified
    >
    > Thanks for the comment, the attached v20250622 version patch has the
    > changes for the same.
    >
    Hi Vignesh,
    
    I have reviewed the patches 0001 and 0002. I do not have any comments
    for 0001 patch. Here are comments for 0002 patch.
    
    1. Initially, I have created a publication on sequence s1.
    postgres=# CREATE PUBLICATION pub1 FOR ALL SEQUENCES;
    CREATE PUBLICATION
    postgres=# ALTER PUBLICATION pub1 SET TABLE t1;
    ALTER PUBLICATION
    postgres=# \d s1
                                 Sequence "public.s1"
      Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache
    --------+-------+---------+---------------------+-----------+---------+-------
     bigint |     1 |       1 | 9223372036854775807 |         1 | no      |     1
    Publications:
        "pub1"
    postgres=# select * from pg_publication_rel;
      oid  | prpubid | prrelid | prqual | prattrs
    -------+---------+---------+--------+---------
     16415 |   16414 |   16388 |        |
    (1 row)
    
    Here, we can set the publication to TABLE or TABLES FOR SCHEMA. Should
    this be allowed?
    If a publication is created on FOR ALL TABLES, such an operation is not allowed.
    
    If we decide to allow it, it is currently not handled correctly as we
    can still see "pub1" in Publications for sequence s1.
    
    2. Similar to the comment given by Shveta in [1] point 3.
    Same behaviour is present for ALTER PUBLICATION
    
    postgres=# ALTER PUBLICATION pub2 ADD SEQUENCES;
    ERROR:  invalid publication object list
    LINE 1: ALTER PUBLICATION pub2 ADD SEQUENCES;
                                       ^
    DETAIL:  One of TABLE, TABLES IN SCHEMA or ALL SEQUENCES must be
    specified before a standalone table or schema name.
    
    postgres=# ALTER PUBLICATION pub2 ADD TABLES;
    ERROR:  invalid publication object list
    LINE 1: ALTER PUBLICATION pub2 ADD TABLES;
                                       ^
    DETAIL:  One of TABLE, TABLES IN SCHEMA or ALL SEQUENCES must be
    specified before a standalone table or schema name.
    
    
    [1]: https://www.postgresql.org/message-id/CAJpy0uAY9sCRCkkVn4qbQeU8NMdLEA_wwBCyV0tvYft_sFST7g%40mail.gmail.com
    
    Thanks and Regards,
    Shlok Kyal
    
    
    
    
  242. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-06-25T03:56:05Z

    On Tue, Jun 24, 2025 at 3:07 PM Nisha Moond <nisha.moond412@gmail.com> wrote:
    >
    > On Sun, Jun 22, 2025 at 8:05 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > Thanks for the comment, the attached v20250622 version patch has the
    > > changes for the same.
    > >
    >
    > Thanks for the patches, please find my review comments for patches 001 and 002:
    >
    
    Please find my further comments on patches 004 and 005:
    (I've no comments for 006)
    
    patch-004:
    
    5) The new fetch_sequence_list() function should be guarded with version checks.
    Without this, CREATE SUBSCRIPTION will always fail when a newer
    subscriber (>=PG19) attempts to create a subscription to an older
    publisher (<PG19).
    e.g., pub1 is a publication on without-patch node, with only tables in it.
    
    postgres=# create subscription sub_oldpub connection 'dbname=postgres
    host=localhost port=8841' publication pub1;
    ERROR:  could not receive list of sequences from the publisher: ERROR:
     relation "pg_catalog.pg_publication_sequences" does not exist
    LINE 2: FROM pg_catalog.pg_publication_sequences ...
    ~~~
    
    6)
    + * not_ready:
    + * If getting tables, if not_ready is false get all tables, otherwise
    + * only get tables that have not reached READY state.
    + * If getting sequences, if not_ready is false get all sequences,
    + * otherwise only get sequences that have not reached READY state (i.e. are
    + * still in INIT state).
    
    I feel the above comment could be reworded slightly for better clarity.
    Suggestion:
    
     * If getting tables and not_ready is false, get all tables, otherwise,
     * only get tables that have not reached READY state.
     * If getting sequences and not_ready is false, get all sequences,
     * otherwise, only get sequences that have not reached READY state (i.e. are
    ~~~
    
    patch-005:
    
    7)
    + /*
    + * Establish the connection to the publisher for sequence synchronization.
    + */
    + LogRepWorkerWalRcvConn =
    + walrcv_connect(MySubscription->conninfo, true, true,
    +    must_use_password,
    +    app_name.data, &err);
    + if (LogRepWorkerWalRcvConn == NULL)
    + ereport(ERROR,
    + errcode(ERRCODE_CONNECTION_FAILURE),
    + errmsg("could not connect to the publisher: %s", err));
    
    The error message should mention the specific process or worker that
    failed to connect, similar to how it's done for other workers like
    slotsync or tablesync.
    
    Suggestion:
     errmsg("sequencesync worker for subscription \"%s\" could not connect
    to the publisher: %s", MySubscription->name, err));
    ~~~
    
    8)
    + CommitTransactionCommand();
    +
    + copy_sequences(LogRepWorkerWalRcvConn, remotesequences, subid);
    +
    + list_free_deep(sequences_not_synced);
    
    Should we also free the 'remotesequences' list here?
    ~~~
    
    --
    Thanks,
    Nisha
    
    
    
    
  243. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-06-25T03:56:08Z

    On Tue, Jun 24, 2025 at 6:44 PM Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    >
    >
    > 1. Initially, I have created a publication on sequence s1.
    > postgres=# CREATE PUBLICATION pub1 FOR ALL SEQUENCES;
    > CREATE PUBLICATION
    > postgres=# ALTER PUBLICATION pub1 SET TABLE t1;
    > ALTER PUBLICATION
    > postgres=# \d s1
    >                              Sequence "public.s1"
    >   Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache
    > --------+-------+---------+---------------------+-----------+---------+-------
    >  bigint |     1 |       1 | 9223372036854775807 |         1 | no      |     1
    > Publications:
    >     "pub1"
    > postgres=# select * from pg_publication_rel;
    >   oid  | prpubid | prrelid | prqual | prattrs
    > -------+---------+---------+--------+---------
    >  16415 |   16414 |   16388 |        |
    > (1 row)
    >
    > Here, we can set the publication to TABLE or TABLES FOR SCHEMA. Should
    > this be allowed?
    > If a publication is created on FOR ALL TABLES, such an operation is not allowed.
    >
    
    Good catch. IMO, this should not be allowed as currently we strictly
    support either ALL SEQUENCES or ALL SEQUENCES with ALL TABLES alone.
    
    thanks
    Shveta
    
    
    
    
  244. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2025-06-25T09:40:04Z

    On Sun, 22 Jun 2025 at 08:05, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 19 Jun 2025 at 11:26, Nisha Moond <nisha.moond412@gmail.com> wrote:
    > >
    > > Hi,
    > >
    > > Here are my review comments for v20250610 patches:
    > >
    > > Patch-0005:sequencesync.c
    > >
    > > 1) report_error_sequences()
    > >
    > > In case there are both missing and mismatched sequences, the ERROR
    > > message logged is -
    > >
    > > ```
    > > 2025-05-28 14:22:19.898 IST [392259] ERROR:  logical replication
    > > sequence synchronization failed for subscription "subs": sequences
    > > ("public"."n84") are missing on the publisher. Additionally,
    > > parameters differ for the remote and local sequences ("public.n1")
    > > ```
    > >
    > > I feel this error message is quite long. Would it be possible to split
    > > it into ERROR and DETAIL? Also, if feasible, we could consider
    > > including a HINT, as was done in previous versions.
    > >
    > > I explored a few possible ways to log this error with a hint. Attached
    > > top-up patch has the suggestion implemented. Please see if it seems
    > > okay to consider.
    >
    > This looks good, merged it.
    > > ~~~
    > >
    > > 2) copy_sequences():
    > > + /* Retrieve the sequence object fetched from the publisher */
    > > + for (int i = 0; i < batch_size; i++)
    > > + {
    > > + LogicalRepSequenceInfo *sequence_info =
    > > lfirst(list_nth_cell(remotesequences, current_index + i));
    > > +
    > > + if (!strcmp(sequence_info->nspname, nspname) &&
    > > + !strcmp(sequence_info->seqname, seqname))
    > > + seqinfo = sequence_info;
    > > + }
    > >
    > > The current logic performs a search through the local sequence list
    > > for each sequence fetched from the publisher, repeating the traverse
    > > of 100(batch size) length of the list per sequence, which may impact
    > > performance.
    > >
    > > To improve efficiency, we can optimize it by sorting the local list
    > > and traverses it only once for matching. Kindly review the
    > > implementation in the attached top-up patch and consider merging it if
    > > it looks good to you.
    >
    > Looks good, merged it.
    >
    > > ~~~
    > >
    > > 3) copy_sequences():
    > > + if (message_level_is_interesting(DEBUG1))
    > > + ereport(DEBUG1,
    > > + errmsg_internal("logical replication synchronization for
    > > subscription \"%s\", sequence \"%s\" has finished",
    > > + MySubscription->name,
    > > + seqinfo->seqname));
    > > +
    > > + batch_succeeded_count++;
    > > + }
    > >
    > > The current debug log might be a bit confusing when sequences with the
    > > same name exist in different schemas. To improve clarity, we could
    > > include the schema name in the message, e.g.,
    > > " ... sequence "schema"."sequence" has finished".
    >
    > Modified
    >
    > > ~~~~
    > >
    > > Few minor comments in doc - Patch-0006 : logical-replication.sgml
    > >
    > > 4)
    > > +  <para>
    > > +   To replicate sequences from a publisher to a subscriber, first publish them
    > > +   using <link linkend="sql-createpublication-params-for-all-sequences">
    > > +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link>.
    > > +  </para>
    > >
    > > I think it would be better to use "To synchronize" instead of "To
    > > replicate" here, to maintain consistency and avoid confusion between
    > > replication and synchronization.
    >
    > Modified
    >
    > > 5)
    > > +   <para>
    > > +    Update the sequences at the publisher side few times.
    > > +<programlisting>
    > >
    > > /side few /side a few /
    > >
    > > 6) Can avoid using multiple "or" in the sentences below:
    > >
    > > 6a)
    > > -   a change set or replication set.  Each publication exists in only
    > > one database.
    > > +   generated from a table or a group of tables or the current state of all
    > > +   sequences, and might also be described as a change set or replication set
    > >
    > > / table or a group of tables/ table, a group of tables/
    >
    > Modified
    >
    > > 6b)
    > > +   Publications may currently only contain tables or sequences. Objects must be
    > > +   added explicitly, except when a publication is created using
    > > +   <literal>FOR TABLES IN SCHEMA</literal>, or <literal>FOR ALL
    > > TABLES</literal>,
    > > +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    > >
    > > / IN SCHEMA</literal>, or <literal>FOR ALL TABLES/ IN
    > > SCHEMA</literal>, <literal>FOR ALL TABLES
    >
    > Modified
    >
    > Thanks for the comment, the attached v20250622 version patch has the
    > changes for the same.
    >
    Hi Vignesh,
    
    I have reviewed the 0004 patch. Here are my comments:
    
    1. I think we need to update the below comment for function
    AlterSubscription_refresh. I feel replacing 'tables' with 'relations'
    would be sufficient.
    /*
    * Build qsorted array of local table oids for faster lookup. This can
    * potentially contain all tables in the database so speed of lookup
    * is important.
    */
    
    2. Similarly as above comment.
    /*
    * Walk over the remote tables and try to match them to locally known
    * tables. If the table is not known locally create a new state for
    * it.
    *
    * Also builds array of local oids of remote tables for the next step.
    */
    
    3. Similarly as above comment.
    /*
    * Next remove state for tables we should not care about anymore using
    * the data we collected above
    */
    Similarly for above comment.
    
    4. Since we are not adding sequences in the list 'sub_remove_rels',
    should we only palloc for (the count of no. of tables)? Is it worth
    the effort?
    /*
    * Rels that we want to remove from subscription and drop any slots
    * and origins corresponding to them.
    */
    sub_remove_rels = palloc(subrel_count * sizeof(SubRemoveRels));
    
    Thanks and Regards,
    Shlok Kyal
    
    
    
    
  245. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2025-06-25T14:12:25Z

    On Sun, 22 Jun 2025 at 08:05, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 19 Jun 2025 at 11:26, Nisha Moond <nisha.moond412@gmail.com> wrote:
    > >
    > > Hi,
    > >
    > > Here are my review comments for v20250610 patches:
    > >
    > > Patch-0005:sequencesync.c
    > >
    > > 1) report_error_sequences()
    > >
    > > In case there are both missing and mismatched sequences, the ERROR
    > > message logged is -
    > >
    > > ```
    > > 2025-05-28 14:22:19.898 IST [392259] ERROR:  logical replication
    > > sequence synchronization failed for subscription "subs": sequences
    > > ("public"."n84") are missing on the publisher. Additionally,
    > > parameters differ for the remote and local sequences ("public.n1")
    > > ```
    > >
    > > I feel this error message is quite long. Would it be possible to split
    > > it into ERROR and DETAIL? Also, if feasible, we could consider
    > > including a HINT, as was done in previous versions.
    > >
    > > I explored a few possible ways to log this error with a hint. Attached
    > > top-up patch has the suggestion implemented. Please see if it seems
    > > okay to consider.
    >
    > This looks good, merged it.
    > > ~~~
    > >
    > > 2) copy_sequences():
    > > + /* Retrieve the sequence object fetched from the publisher */
    > > + for (int i = 0; i < batch_size; i++)
    > > + {
    > > + LogicalRepSequenceInfo *sequence_info =
    > > lfirst(list_nth_cell(remotesequences, current_index + i));
    > > +
    > > + if (!strcmp(sequence_info->nspname, nspname) &&
    > > + !strcmp(sequence_info->seqname, seqname))
    > > + seqinfo = sequence_info;
    > > + }
    > >
    > > The current logic performs a search through the local sequence list
    > > for each sequence fetched from the publisher, repeating the traverse
    > > of 100(batch size) length of the list per sequence, which may impact
    > > performance.
    > >
    > > To improve efficiency, we can optimize it by sorting the local list
    > > and traverses it only once for matching. Kindly review the
    > > implementation in the attached top-up patch and consider merging it if
    > > it looks good to you.
    >
    > Looks good, merged it.
    >
    > > ~~~
    > >
    > > 3) copy_sequences():
    > > + if (message_level_is_interesting(DEBUG1))
    > > + ereport(DEBUG1,
    > > + errmsg_internal("logical replication synchronization for
    > > subscription \"%s\", sequence \"%s\" has finished",
    > > + MySubscription->name,
    > > + seqinfo->seqname));
    > > +
    > > + batch_succeeded_count++;
    > > + }
    > >
    > > The current debug log might be a bit confusing when sequences with the
    > > same name exist in different schemas. To improve clarity, we could
    > > include the schema name in the message, e.g.,
    > > " ... sequence "schema"."sequence" has finished".
    >
    > Modified
    >
    > > ~~~~
    > >
    > > Few minor comments in doc - Patch-0006 : logical-replication.sgml
    > >
    > > 4)
    > > +  <para>
    > > +   To replicate sequences from a publisher to a subscriber, first publish them
    > > +   using <link linkend="sql-createpublication-params-for-all-sequences">
    > > +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link>.
    > > +  </para>
    > >
    > > I think it would be better to use "To synchronize" instead of "To
    > > replicate" here, to maintain consistency and avoid confusion between
    > > replication and synchronization.
    >
    > Modified
    >
    > > 5)
    > > +   <para>
    > > +    Update the sequences at the publisher side few times.
    > > +<programlisting>
    > >
    > > /side few /side a few /
    > >
    > > 6) Can avoid using multiple "or" in the sentences below:
    > >
    > > 6a)
    > > -   a change set or replication set.  Each publication exists in only
    > > one database.
    > > +   generated from a table or a group of tables or the current state of all
    > > +   sequences, and might also be described as a change set or replication set
    > >
    > > / table or a group of tables/ table, a group of tables/
    >
    > Modified
    >
    > > 6b)
    > > +   Publications may currently only contain tables or sequences. Objects must be
    > > +   added explicitly, except when a publication is created using
    > > +   <literal>FOR TABLES IN SCHEMA</literal>, or <literal>FOR ALL
    > > TABLES</literal>,
    > > +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    > >
    > > / IN SCHEMA</literal>, or <literal>FOR ALL TABLES/ IN
    > > SCHEMA</literal>, <literal>FOR ALL TABLES
    >
    > Modified
    >
    > Thanks for the comment, the attached v20250622 version patch has the
    > changes for the same.
    >
    Hi Vignesh,
    
    I tested with all patches applied. I have a comment:
    
    Let consider following case:
    On publisher create a publication pub1 on all sequence. publication
    has sequence s1. The curr value of s1 is 2
    and On subscriber we have subscription on pub1 and sequence s1 has
    value 5. Now we run:
    "ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES"
    
    Now on subscriber currval still show '5':
    postgres=# select currval('s1');
     currval
    ---------
           5
    (1 row)
    
    But when we do nextval on s1 on subscriber we get '3'. Which is
    correct assuming sequence is synced:
    postgres=# select nextval('s1');
     nextval
    ---------
           3
    (1 row)
    postgres=# select currval('s1');
     currval
    ---------
           3
    (1 row)
    
    Is this behaviour expected? I feel the initial " select
    currval('s1');" should have displayed '2'. Thoughts?
    
    Thanks and Regards,
    Shlok Kyal
    
    
    
    
  246. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-06-27T03:20:03Z

    On Wed, Jun 25, 2025 at 7:42 PM Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    >
    > On Sun, 22 Jun 2025 at 08:05, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Thu, 19 Jun 2025 at 11:26, Nisha Moond <nisha.moond412@gmail.com> wrote:
    > > >
    > > > Hi,
    > > >
    > > > Here are my review comments for v20250610 patches:
    > > >
    > > > Patch-0005:sequencesync.c
    > > >
    > > > 1) report_error_sequences()
    > > >
    > > > In case there are both missing and mismatched sequences, the ERROR
    > > > message logged is -
    > > >
    > > > ```
    > > > 2025-05-28 14:22:19.898 IST [392259] ERROR:  logical replication
    > > > sequence synchronization failed for subscription "subs": sequences
    > > > ("public"."n84") are missing on the publisher. Additionally,
    > > > parameters differ for the remote and local sequences ("public.n1")
    > > > ```
    > > >
    > > > I feel this error message is quite long. Would it be possible to split
    > > > it into ERROR and DETAIL? Also, if feasible, we could consider
    > > > including a HINT, as was done in previous versions.
    > > >
    > > > I explored a few possible ways to log this error with a hint. Attached
    > > > top-up patch has the suggestion implemented. Please see if it seems
    > > > okay to consider.
    > >
    > > This looks good, merged it.
    > > > ~~~
    > > >
    > > > 2) copy_sequences():
    > > > + /* Retrieve the sequence object fetched from the publisher */
    > > > + for (int i = 0; i < batch_size; i++)
    > > > + {
    > > > + LogicalRepSequenceInfo *sequence_info =
    > > > lfirst(list_nth_cell(remotesequences, current_index + i));
    > > > +
    > > > + if (!strcmp(sequence_info->nspname, nspname) &&
    > > > + !strcmp(sequence_info->seqname, seqname))
    > > > + seqinfo = sequence_info;
    > > > + }
    > > >
    > > > The current logic performs a search through the local sequence list
    > > > for each sequence fetched from the publisher, repeating the traverse
    > > > of 100(batch size) length of the list per sequence, which may impact
    > > > performance.
    > > >
    > > > To improve efficiency, we can optimize it by sorting the local list
    > > > and traverses it only once for matching. Kindly review the
    > > > implementation in the attached top-up patch and consider merging it if
    > > > it looks good to you.
    > >
    > > Looks good, merged it.
    > >
    > > > ~~~
    > > >
    > > > 3) copy_sequences():
    > > > + if (message_level_is_interesting(DEBUG1))
    > > > + ereport(DEBUG1,
    > > > + errmsg_internal("logical replication synchronization for
    > > > subscription \"%s\", sequence \"%s\" has finished",
    > > > + MySubscription->name,
    > > > + seqinfo->seqname));
    > > > +
    > > > + batch_succeeded_count++;
    > > > + }
    > > >
    > > > The current debug log might be a bit confusing when sequences with the
    > > > same name exist in different schemas. To improve clarity, we could
    > > > include the schema name in the message, e.g.,
    > > > " ... sequence "schema"."sequence" has finished".
    > >
    > > Modified
    > >
    > > > ~~~~
    > > >
    > > > Few minor comments in doc - Patch-0006 : logical-replication.sgml
    > > >
    > > > 4)
    > > > +  <para>
    > > > +   To replicate sequences from a publisher to a subscriber, first publish them
    > > > +   using <link linkend="sql-createpublication-params-for-all-sequences">
    > > > +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link>.
    > > > +  </para>
    > > >
    > > > I think it would be better to use "To synchronize" instead of "To
    > > > replicate" here, to maintain consistency and avoid confusion between
    > > > replication and synchronization.
    > >
    > > Modified
    > >
    > > > 5)
    > > > +   <para>
    > > > +    Update the sequences at the publisher side few times.
    > > > +<programlisting>
    > > >
    > > > /side few /side a few /
    > > >
    > > > 6) Can avoid using multiple "or" in the sentences below:
    > > >
    > > > 6a)
    > > > -   a change set or replication set.  Each publication exists in only
    > > > one database.
    > > > +   generated from a table or a group of tables or the current state of all
    > > > +   sequences, and might also be described as a change set or replication set
    > > >
    > > > / table or a group of tables/ table, a group of tables/
    > >
    > > Modified
    > >
    > > > 6b)
    > > > +   Publications may currently only contain tables or sequences. Objects must be
    > > > +   added explicitly, except when a publication is created using
    > > > +   <literal>FOR TABLES IN SCHEMA</literal>, or <literal>FOR ALL
    > > > TABLES</literal>,
    > > > +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    > > >
    > > > / IN SCHEMA</literal>, or <literal>FOR ALL TABLES/ IN
    > > > SCHEMA</literal>, <literal>FOR ALL TABLES
    > >
    > > Modified
    > >
    > > Thanks for the comment, the attached v20250622 version patch has the
    > > changes for the same.
    > >
    > Hi Vignesh,
    >
    > I tested with all patches applied. I have a comment:
    >
    > Let consider following case:
    > On publisher create a publication pub1 on all sequence. publication
    > has sequence s1. The curr value of s1 is 2
    > and On subscriber we have subscription on pub1 and sequence s1 has
    > value 5. Now we run:
    > "ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES"
    >
    > Now on subscriber currval still show '5':
    > postgres=# select currval('s1');
    >  currval
    > ---------
    >        5
    > (1 row)
    >
    > But when we do nextval on s1 on subscriber we get '3'. Which is
    > correct assuming sequence is synced:
    > postgres=# select nextval('s1');
    >  nextval
    > ---------
    >        3
    > (1 row)
    > postgres=# select currval('s1');
    >  currval
    > ---------
    >        3
    > (1 row)
    >
    > Is this behaviour expected? I feel the initial " select
    > currval('s1');" should have displayed '2'. Thoughts?
    
    As per docs at [1], currval returns the value most recently obtained
    by nextval for this sequence in the current session. So behaviour is
    in alignment with docs. I tested this across multiple sessions,
    regardless of whether sequence synchronization occurs or not. The
    behavior remains consistent across sessions. As an example, if in
    session2 the sequence has advanced to a value of 10 by calling
    nextval, the currval in session1 still shows the previous value of 3,
    which was obtained by nextval in session1. So, it seems expected to
    me. But let's wait for Vignesh's comments on this.
    
    [1]: https://www.postgresql.org/docs/current/functions-sequence.html
    
    thanks
    Shveta
    
    
    
    
  247. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-06-30T09:50:00Z

    On Fri, Jun 27, 2025 at 8:50 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Wed, Jun 25, 2025 at 7:42 PM Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    > > Hi Vignesh,
    > >
    > > I tested with all patches applied. I have a comment:
    > >
    > > Let consider following case:
    > > On publisher create a publication pub1 on all sequence. publication
    > > has sequence s1. The curr value of s1 is 2
    > > and On subscriber we have subscription on pub1 and sequence s1 has
    > > value 5. Now we run:
    > > "ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES"
    > >
    > > Now on subscriber currval still show '5':
    > > postgres=# select currval('s1');
    > >  currval
    > > ---------
    > >        5
    > > (1 row)
    > >
    > > But when we do nextval on s1 on subscriber we get '3'. Which is
    > > correct assuming sequence is synced:
    > > postgres=# select nextval('s1');
    > >  nextval
    > > ---------
    > >        3
    > > (1 row)
    > > postgres=# select currval('s1');
    > >  currval
    > > ---------
    > >        3
    > > (1 row)
    > >
    > > Is this behaviour expected? I feel the initial " select
    > > currval('s1');" should have displayed '2'. Thoughts?
    >
    > As per docs at [1], currval returns the value most recently obtained
    > by nextval for this sequence in the current session. So behaviour is
    > in alignment with docs. I tested this across multiple sessions,
    > regardless of whether sequence synchronization occurs or not. The
    > behavior remains consistent across sessions. As an example, if in
    > session2 the sequence has advanced to a value of 10 by calling
    > nextval, the currval in session1 still shows the previous value of 3,
    > which was obtained by nextval in session1. So, it seems expected to
    > me. But let's wait for Vignesh's comments on this.
    >
    > [1]: https://www.postgresql.org/docs/current/functions-sequence.html
    >
    
    I also agree. It is expected behavior, as currval returns the last
    nextval generated in the same session. I've also observed this across
    multiple sessions.
    
    --
    Thanks,
    Nisha
    
    
    
    
  248. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-06-30T09:50:57Z

    On Tue, Jun 24, 2025 at 10:37 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > >
    > > Thanks for the comment, the attached v20250622 version patch has the
    > > changes for the same.
    > >
    >
    > Thanks for the patches, I am not done with review yet, but please find
    > the feedback so far:
    >
    
    Thanks for the review.
    
    >
    > 1)
    > + if (!OidIsValid(seq_relid))
    > + ereport(ERROR,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("sequence \"%s.%s\" does not exist",
    > +    schema_name, sequence_name));
    >
    > ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE might not be a correct error
    > code here. Shall we have ERRCODE_UNDEFINED_OBJECT? Thoughts?
    >
    
    +1
    Updated to ERRCODE_UNDEFINED_OBJECT code in v20250630
    
    >
    > 2)
    > tab-complete here shows correctly:
    >
    > postgres=# CREATE PUBLICATION pub6 FOR ALL
    > SEQUENCES  TABLES
    >
    > But tab-complete for these 2 commands does not show anything:
    >
    > postgres=# CREATE PUBLICATION pub6 FOR ALL TABLES,
    > postgres=# CREATE PUBLICATION pub6 FOR ALL SEQUENCES,
    >
    > We shall specify SEQUENCES/TABLES in above commands. IIUC, we do not
    > support any other combination like (table <name>, tables in schema
    > <name>) once we get ALL clause in command. So it is safe to display
    > tab-complete as either TABLES or SEQUENECS in above.
    >
    
    Tab-completion is not supported after a comma (,) in any other cases.
    For example, the following commands are valid, but tab-completion does
    not work after the comma:
    
    CREATE PUBLICATION pub7 FOR TABLE t1, TABLES IN SCHEMA public;
    CREATE PUBLICATION pub7 FOR TABLES IN SCHEMA public, TABLES IN SCHEMA schema2;
    
    I feel we can keep the behavior consistent in this case too. Thoughts?
    
    > 3)
    > postgres=#  CREATE publication pub1 for sequences;
    > ERROR:  invalid publication object list
    > LINE 1: CREATE publication pub1 for sequences;
    >                                  ^
    > DETAIL:  One of TABLE, TABLES IN SCHEMA or ALL SEQUENCES must be
    > specified before a standalone table or schema name.
    >
    >
    > This message is not correct as we can not have ALL SEQUENCES *before*
    > a standalone table or schema name. The problem is that gram.y is
    > taking *sequences* as a table or schema name. I noticed that it does
    > same with *tables* as well:
    >
    > postgres=#  CREATE publication pub1 for tables;
    > ERROR:  invalid publication object list
    > LINE 1: CREATE publication pub1 for tables;
    >                                   ^
    > DETAIL:  One of TABLE, TABLES IN SCHEMA or ALL SEQUENCES must be
    > specified before a standalone table or schema name.
    >
    >
    > But since gram.y here can not identify an in-between missing keyword
    > *all*, thus it is considering it (tables/sequenecs) as a literal/name
    > instead of keyword. We can revert back to old message in such a case.
    > I am unable to think of a good solution here.
    >
    
    Done, reverted to the original message.
    
    >
    > 4)
    > I think the error here is wrong as we are not trying to specify
    > multiple all-tables entries.
    >
    > postgres=# CREATE PUBLICATION pub6 for all tables, tables in schema public;
    > ERROR:  invalid publication object list
    > LINE 1: CREATE PUBLICATION pub6 for all tables, tables in schema pub...
    >
    >                                                 ^
    > DETAIL:  ALL TABLES can be specified only once.
    >
    
    The parser cannot distinguish between "TABLES" and "TABLES IN SCHEMA"
    while building all_object_list for "FOR ALL ...".
    To address this, the duplicate check has been moved to
    CreatePublication, and a syntax error is now raised for cases
    mentioned above.
    
    >
    > 5)
    > The log messages still has some scope of improvement:
    >
    > 2025-06-24 08:52:17.988 IST [110359] LOG:  logical replication
    > sequence synchronization worker for subscription "sub1" has started
    > 2025-06-24 08:52:18.029 IST [110359] LOG:  logical replication
    > sequence synchronization for subscription "sub1" - total
    > unsynchronized: 3
    > 2025-06-24 08:52:18.090 IST [110359] LOG:  logical replication
    > sequence synchronization for subscription "sub1" - batch #1 = 3
    > attempted, 0 succeeded, 2 mismatched, 1 missing
    > 2025-06-24 08:52:18.091 IST [110359] ERROR:  logical replication
    > sequence synchronization failed for subscription "sub1"
    > 2025-06-24 08:52:18.091 IST [110359] DETAIL:  Sequences
    > ("public.myseq100") are missing on the publisher. Additionally,
    > parameters differ for the remote and local sequences
    > ("public.myseq101", "public.myseq102").
    > 2025-06-24 08:52:18.091 IST [110359] HINT:  Use ALTER SUBSCRIPTION ...
    > REFRESH PUBLICATION or use ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > SEQUENCES. Alter or re-create local sequences to have the same
    > parameters as the remote sequences
    >
    >
    > a)
    > Sequences ("public.myseq100") are missing on the publisher.
    > Additionally, parameters differ for the remote and local sequences
    > ("public.myseq101", "public.myseq102").
    >
    > Shall we change this to:
    > missing sequence(s) on publisher: ("public.myseq100"); mismatched
    > sequences(s) on subscriber: ("public.myseq101", "public.myseq102")
    >
    > It will then be similar to the previous log pattern ( 3 attempted, 0
    > succeeded etc) instead of being more verbal. Thoughts?
    >
    >
    > b)
    > Hints are a little odd. First line of hint is just saying to use
    > 'ALTER SUBSCRIPTION' without giving any purpose. While the second line
    > of hint is giving the purpose of alter-sequences.
    >
    > Shall we have?
    > For missing sequences, use ALTER SUBSCRIPTION with either REFRESH
    > PUBLICATION or REFRESH PUBLICATION SEQUENCES
    > For mismatched sequences, alter or re-create local sequences to have
    > matching parameters as publishers.
    >
    > Thoughts?
    >
    
    Updated the messages as suggested.
    
    > 6)
    > postgres=# create publication pub1 for table tab1, all sequences;
    > ERROR:  syntax error at or near "all"
    > LINE 1: create publication pub1 for table tab1, all sequences;
    >
    > We can mention in commit msg that this combination is also not
    > supported or what all combinations are supported. Currently it is not
    > clear f
    
    Done.
    ~~~~
    
    Please find the attached v20250630 patch set addressing above comments
    and other comments in [1],[2],[3] and [4].
    
    [1] https://www.postgresql.org/message-id/CABdArM7h1qQLUb_S7i6MrLPEtHXnX%2BY2fPQaSnqhCdHktcQk5Q%40mail.gmail.com
    [2] https://www.postgresql.org/message-id/CANhcyEVbdambw%3DaVVuW0RrhQ7Lkqad%3DCdrvVA8FP6Xb%2BkP_Qzg%40mail.gmail.com
    [3] https://www.postgresql.org/message-id/CABdArM5mwL8WtGWdDdYT98ddYaB%3D3N6cfPBncvnh682X1GfbVQ%40mail.gmail.com
    [4] https://www.postgresql.org/message-id/CANhcyEWKhHWFzpdAF6czbwq76NRDNCecDqQNtN6Bomn26mqHFw%40mail.gmail.com
    
    --
    Thanks,
    Nisha
    
  249. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-06-30T09:51:48Z

    On Wed, Jun 25, 2025 at 9:26 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Tue, Jun 24, 2025 at 6:44 PM Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    > >
    > >
    > > 1. Initially, I have created a publication on sequence s1.
    > > postgres=# CREATE PUBLICATION pub1 FOR ALL SEQUENCES;
    > > CREATE PUBLICATION
    > > postgres=# ALTER PUBLICATION pub1 SET TABLE t1;
    > > ALTER PUBLICATION
    > > postgres=# \d s1
    > >                              Sequence "public.s1"
    > >   Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache
    > > --------+-------+---------+---------------------+-----------+---------+-------
    > >  bigint |     1 |       1 | 9223372036854775807 |         1 | no      |     1
    > > Publications:
    > >     "pub1"
    > > postgres=# select * from pg_publication_rel;
    > >   oid  | prpubid | prrelid | prqual | prattrs
    > > -------+---------+---------+--------+---------
    > >  16415 |   16414 |   16388 |        |
    > > (1 row)
    > >
    > > Here, we can set the publication to TABLE or TABLES FOR SCHEMA. Should
    > > this be allowed?
    > > If a publication is created on FOR ALL TABLES, such an operation is not allowed.
    > >
    >
    > Good catch. IMO, this should not be allowed as currently we strictly
    > support either ALL SEQUENCES or ALL SEQUENCES with ALL TABLES alone.
    >
    
    +1
    
    A similar situation existed for the ALTER PUBLICATION ... ADD ...
    command as reported in [1] (point #3).
    This has been addressed in v20250630, where similar to ALL TABLES, ADD
    or SET operations are now disallowed for ALL SEQUENCES publications.
    
    [1] https://www.postgresql.org/message-id/CABdArM7h1qQLUb_S7i6MrLPEtHXnX%2BY2fPQaSnqhCdHktcQk5Q%40mail.gmail.com
    
    --
    Thanks,
    Nisha
    
    
    
    
  250. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-06-30T09:53:50Z

    On Wed, Jun 25, 2025 at 3:10 PM Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    >
    >
    > 4. Since we are not adding sequences in the list 'sub_remove_rels',
    > should we only palloc for (the count of no. of tables)? Is it worth
    > the effort?
    > /*
    > * Rels that we want to remove from subscription and drop any slots
    > * and origins corresponding to them.
    > */
    > sub_remove_rels = palloc(subrel_count * sizeof(SubRemoveRels));
    >
    
    The sub_remove_rels array allocates memory for all relations in the
    subscription, even though it only uses entries for those that are
    actually removed.
    While this may result in unnecessary allocation, even when only tables
    are involved. OTOH, as it’s a short-lived variable, pre-allocating can
    help with performance.
    This requires further analysis, I plan to handle this in the next version.
    
    --
    Thanks,
    Nisha
    
    
    
    
  251. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-01T04:21:08Z

    On Mon, Jun 30, 2025 at 3:21 PM Nisha Moond <nisha.moond412@gmail.com> wrote:
    >
    > Tab-completion is not supported after a comma (,) in any other cases.
    > For example, the following commands are valid, but tab-completion does
    > not work after the comma:
    >
    > CREATE PUBLICATION pub7 FOR TABLE t1, TABLES IN SCHEMA public;
    > CREATE PUBLICATION pub7 FOR TABLES IN SCHEMA public, TABLES IN SCHEMA schema2;
    >
    > I feel we can keep the behavior consistent in this case too. Thoughts?
    >
    
    Yes, let's keep the behaviour same. No need to make a change.
    
    thanks
    Shveta
    
    
    
    
  252. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-01T09:50:14Z

    On Mon, Jun 30, 2025 at 3:21 PM Nisha Moond <nisha.moond412@gmail.com> wrote:
    >
    > Please find the attached v20250630 patch set addressing above comments
    > and other comments in [1],[2],[3] and [4].
    
    Thanks for the patches. I am still in process of reviewing it but
    please find few comments:
    
    1)
    + if (pset.sversion >= 180000)
    + appendPQExpBuffer(&buf,
    +   ",\n  puballsequences AS \"%s\"",
    +   gettext_noop("All sequences"));
    
    The server version check throughout the patch can be modified to 19000
    as a new branch is created now.
    
    2)
    + bool all_pub; /* Special publication for all tables,
    + * sequecnes */
    
    a) Typo: sequecnes --> sequences
    b) It is not clear from the comment that when will it be true? Will it
    be set when either of all-tables or all-sequences is given or does it
    need both?
    
    3)
    postgres=# create publication pub1 for all sequences WITH ( PUBLISH='delete');
    CREATE PUBLICATION
    postgres=# create publication pub2 for all tables, sequences WITH
    (PUBLISH='update');
    CREATE PUBLICATION
    
    For the first command, 'WITH ( publication_parameter..' is useless.
    For the second command, it is applicable only for 'all tables'.
    
    a) I am not sure if we even allow WITH in the first command?
    b) In the second command, even if we allow it, there should be some
    sort of NOTICE informing that it is applicable only to 'TABLES'.
    
    Thoughts?
    
    Also we allowed altering publication_parameter for all-sequences publication:
    
    postgres=# alter publication pub1 set (publish='insert,update');
    ALTER PUBLICATION
    
    c) Should this be restricted as well? Thoughts?
    
    thanks
    Shveta
    
    
    
    
  253. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-03T09:37:16Z

    Few more concerns:
    
    4)
    In UpdateSubscriptionRelState():
            if (!HeapTupleIsValid(tup))
                    elog(ERROR, "subscription table %u in subscription %u
    does not exist",
                             relid, subid);
    
    table-->relation as now it can be hit for both sequence and table.
    
    5)
    In LogicalRepSyncSequences, why are we allocating it in a permanent
    memory context?
    
    + /* Allocate the tracking info in a permanent memory context. */
    + oldctx = MemoryContextSwitchTo(CacheMemoryContext);
    + foreach_ptr(SubscriptionRelState, seq_state, sequences)
    + {
    + SubscriptionRelState *rstate = palloc(sizeof(SubscriptionRelState));
    +
    + memcpy(rstate, seq_state, sizeof(SubscriptionRelState));
    + sequences_not_synced = lappend(sequences_not_synced, rstate);
    + }
    + MemoryContextSwitchTo(oldctx);
    
    Same for 'seq_info' allocation.
    
    6)
    In LogicalRepSyncSequences, can you please help me understand this:
    Why have we first created new list 'sequences_not_synced' from
    'sequences' list, both have same elements of type
    SubscriptionRelState; and then used that newly created
    'sequences_not_synced list' to create remotesequences list having
    element type LogicalRepSequenceInfo. Why didn't we use 'sequences'
    list directly to create 'remotesequences' list?
    
    7)
    In this function we have 2 variables: seqinfo and seq_info. We are
    using seqinfo to create seq_info. The names are very confusing.
    Difficult to differentiate between the two.
    
    In copy_sequences() too we have similarly named variables: seqinfo and
    sequence_info.
    
    Can we choose different names here?
    
    8)
    Why have we named argument of copy_sequences() as remotesequences?
    IIUC, these are the sequences fetched from pg_subscription_rel and its
    elements even maintain a field 'localrelid'. The name is thus
    confusing as it has local data. Perhaps we can name it as
    candidate_sequences or init_sequences (i.e. sequences in init state)
    or any other suitable name.
    
    thanks
    Shveta
    
    
    
    
  254. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-04T10:23:37Z

    On Tue, 1 Jul 2025 at 15:20, shveta malik <shveta.malik@gmail.com> wrote:
    > On Mon, Jun 30, 2025 at 3:21 PM Nisha Moond <nisha.moond412@gmail.com> wrote:
    > >
    > > Please find the attached v20250630 patch set addressing above comments
    > > and other comments in [1],[2],[3] and [4].
    >
    > Thanks for the patches. I am still in process of reviewing it but
    > please find few comments:
    >
    > 1)
    > + if (pset.sversion >= 180000)
    > + appendPQExpBuffer(&buf,
    > +   ",\n  puballsequences AS \"%s\"",
    > +   gettext_noop("All sequences"));
    >
    > The server version check throughout the patch can be modified to 19000
    > as a new branch is created now.
    
    Modified
    
    > 2)
    > + bool all_pub; /* Special publication for all tables,
    > + * sequecnes */
    >
    > a) Typo: sequecnes --> sequences
    
    Modified
    
    > b) It is not clear from the comment that when will it be true? Will it
    > be set when either of all-tables or all-sequences is given or does it
    > need both?
    
    Updated the comments
    
    > 3)
    > postgres=# create publication pub1 for all sequences WITH ( PUBLISH='delete');
    > CREATE PUBLICATION
    > postgres=# create publication pub2 for all tables, sequences WITH
    > (PUBLISH='update');
    > CREATE PUBLICATION
    >
    > For the first command, 'WITH ( publication_parameter..' is useless.
    > For the second command, it is applicable only for 'all tables'.
    >
    > a) I am not sure if we even allow WITH in the first command?
    > b) In the second command, even if we allow it, there should be some
    > sort of NOTICE informing that it is applicable only to 'TABLES'.
    >
    > Thoughts?
    >
    > Also we allowed altering publication_parameter for all-sequences publication:
    >
    > postgres=# alter publication pub1 set (publish='insert,update');
    > ALTER PUBLICATION
    >
    > c) Should this be restricted as well? Thoughts?
    
    We have documented that the parameter of with clause is not applicable
    for sequences. I feel that all the above statements are ok with the
    documentation mentioned.
    
    Regarding the comments from [1].
    > 5)
    > In LogicalRepSyncSequences, why are we allocating it in a permanent
    > memory context?
    >
    > + /* Allocate the tracking info in a permanent memory context. */
    > + oldctx = MemoryContextSwitchTo(CacheMemoryContext);
    > + foreach_ptr(SubscriptionRelState, seq_state, sequences)
    > + {
    > + SubscriptionRelState *rstate = palloc(sizeof(SubscriptionRelState));
    > +
    > + memcpy(rstate, seq_state, sizeof(SubscriptionRelState));
    > + sequences_not_synced = lappend(sequences_not_synced, rstate);
    > + }
    > + MemoryContextSwitchTo(oldctx);
    >
    > Same for 'seq_info' allocation.
    
    When we are in between a transaction we will be using
    TopTransactionContext. We can palloc() in TopTransactionContext and
    safely use that memory throughout the transaction. But we cannot
    cannot access memory allocated in TopTransactionContext after
    CommitTransaction() finishes, because TopTransactionContext is
    explicitly reset (or deleted) at the end of the transaction.
    This is the reason we have to use CacheMemoryContext here.
    
    The rest of the comments are fixed.
    
    Also one of the pending comment from [2] is fixed.
    > 4. Since we are not adding sequences in the list 'sub_remove_rels',
    > should we only palloc for (the count of no. of tables)? Is it worth
    > the effort?
    > /*
    > * Rels that we want to remove from subscription and drop any slots
    > * and origins corresponding to them.
    > */
    > sub_remove_rels = palloc(subrel_count * sizeof(SubRemoveRels));
    
    The attached v20250704 version patch has the changes for the same.
    [1] - https://www.postgresql.org/message-id/CAJpy0uD%2B7UtDs9%3DCx03BAckMPDdW7C6ifGF_Lc54B8iH6RNXWQ%40mail.gmail.com
    [2] - https://www.postgresql.org/message-id/CANhcyEWKhHWFzpdAF6czbwq76NRDNCecDqQNtN6Bomn26mqHFw%40mail.gmail.com
    
    Regards,
    Vignesh
    
  255. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-07T09:07:43Z

    On Fri, Jul 4, 2025 at 3:53 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 1 Jul 2025 at 15:20, shveta malik <shveta.malik@gmail.com> wrote:
    > > On Mon, Jun 30, 2025 at 3:21 PM Nisha Moond <nisha.moond412@gmail.com> wrote:
    > > >
    > > > Please find the attached v20250630 patch set addressing above comments
    > > > and other comments in [1],[2],[3] and [4].
    > >
    > > Thanks for the patches. I am still in process of reviewing it but
    > > please find few comments:
    > >
    > > 1)
    > > + if (pset.sversion >= 180000)
    > > + appendPQExpBuffer(&buf,
    > > +   ",\n  puballsequences AS \"%s\"",
    > > +   gettext_noop("All sequences"));
    > >
    > > The server version check throughout the patch can be modified to 19000
    > > as a new branch is created now.
    >
    > Modified
    >
    > > 2)
    > > + bool all_pub; /* Special publication for all tables,
    > > + * sequecnes */
    > >
    > > a) Typo: sequecnes --> sequences
    >
    > Modified
    >
    > > b) It is not clear from the comment that when will it be true? Will it
    > > be set when either of all-tables or all-sequences is given or does it
    > > need both?
    >
    > Updated the comments
    >
    > > 3)
    > > postgres=# create publication pub1 for all sequences WITH ( PUBLISH='delete');
    > > CREATE PUBLICATION
    > > postgres=# create publication pub2 for all tables, sequences WITH
    > > (PUBLISH='update');
    > > CREATE PUBLICATION
    > >
    > > For the first command, 'WITH ( publication_parameter..' is useless.
    > > For the second command, it is applicable only for 'all tables'.
    > >
    > > a) I am not sure if we even allow WITH in the first command?
    > > b) In the second command, even if we allow it, there should be some
    > > sort of NOTICE informing that it is applicable only to 'TABLES'.
    > >
    > > Thoughts?
    > >
    > > Also we allowed altering publication_parameter for all-sequences publication:
    > >
    > > postgres=# alter publication pub1 set (publish='insert,update');
    > > ALTER PUBLICATION
    > >
    > > c) Should this be restricted as well? Thoughts?
    >
    > We have documented that the parameter of with clause is not applicable
    > for sequences. I feel that all the above statements are ok with the
    > documentation mentioned.
    >
    > Regarding the comments from [1].
    > > 5)
    > > In LogicalRepSyncSequences, why are we allocating it in a permanent
    > > memory context?
    > >
    > > + /* Allocate the tracking info in a permanent memory context. */
    > > + oldctx = MemoryContextSwitchTo(CacheMemoryContext);
    > > + foreach_ptr(SubscriptionRelState, seq_state, sequences)
    > > + {
    > > + SubscriptionRelState *rstate = palloc(sizeof(SubscriptionRelState));
    > > +
    > > + memcpy(rstate, seq_state, sizeof(SubscriptionRelState));
    > > + sequences_not_synced = lappend(sequences_not_synced, rstate);
    > > + }
    > > + MemoryContextSwitchTo(oldctx);
    > >
    > > Same for 'seq_info' allocation.
    >
    > When we are in between a transaction we will be using
    > TopTransactionContext. We can palloc() in TopTransactionContext and
    > safely use that memory throughout the transaction. But we cannot
    > cannot access memory allocated in TopTransactionContext after
    > CommitTransaction() finishes, because TopTransactionContext is
    > explicitly reset (or deleted) at the end of the transaction.
    > This is the reason we have to use CacheMemoryContext here.
    >
    
    Okay. I see. Thanks for the details. Can we add this info in comments,
    something like:
    Allocate the tracking information in a permanent memory context to
    ensure it remains accessible across multiple transactions during the
    sequence copy process. The memory will be released once the copy is
    finished.
    
    > The rest of the comments are fixed.
    
    Thank you for the patches. I am not done with review yet, but please
    find the comments so far:
    
    
    1)
    LogicalRepSyncSequences()
    
    + /* Allocate the sequences information in a permanent memory context. */
    + oldctx = MemoryContextSwitchTo(CacheMemoryContext);
    +
    + /* Get the sequences that should be synchronized. */
    + subsequences = GetSubscriptionRelations(subid, false, true, true);
    
    Here too we are using CacheMemoryContext? 'subsequences' is only used
    in given function and not in copy_sequeneces. I guess, we start
    multiple transactions in given function and thus make it essential to
    allocate subsequences in CacheMemoryContext. But why are we doing
    StartTransactionCommand twice? Is this intentional? Can we do it once
    before GetSubscriptionRelations() and commit it once after for-loop is
    over? IIUC, then we will not need CacheMemoryContext here.
    
    2)
    logicalrep_seqsyncworker_set_failuretime()
    
    a) This function is extern'ed in worker_internal.h. But I do not see
    its usage outside launcher.c. Is it a mistake?
    
    b) Also, do we really need logicalrep_seqsyncworker_set_failuretime?
    Is it better to move its logic instead in
    logicalrep_seqsyncworker_set_failuretime()?
    
    3)
    SyncFetchRelationStates:
    Earlier the name was FetchTableStates. If we really want to  use the
    'Sync' keyword, we can name it FetchRelationSyncStates, as we are
    fetching sync-status only. Thoughts?
    
    4)
    ProcessSyncingSequencesForApply():
    +
    + if (rstate->state != SUBREL_STATE_INIT)
    + continue;
    
    Why do we expect that rstate->state is not INIT at this time when we
    have fetched only INIT sequences in sequence_states_not_ready. Shall
    this be assert? If there is a valid scenario where it can be READY
    here, please add comments.
    
    5)
    + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    +    now, wal_retrieve_retry_interval))
    + {
    + MyLogicalRepWorker->sequencesync_failure_time = 0;
    +
    + logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    + MyLogicalRepWorker->dbid,
    + MySubscription->oid,
    + MySubscription->name,
    + MyLogicalRepWorker->userid,
    + InvalidOid,
    + DSM_HANDLE_INVALID);
    + break;
    + }
    
    We set sequencesync_failure_time to 0, but if logicalrep_worker_launch
    is not able to launch the worker due to some reason, next time it will
    not even wait for 'wal_retrieve_retry_interval time' to attempt
    restarting it again. Is that intentional?
    
    In other workflows such as while launching table-sync or apply worker,
     this scenario does not arise. This is because we maintain start_time
    there which can never be 0 instead of failure time and before
    attempting to start the workers, we set start_time to current time.
    The seq-sync failure-time OTOH is only set to non-null in
    logicalrep_seqsyncworker_failure() and it is not necessary that we
    will hit that function as the  logicalrep_worker_launch() may fail
    before that itself. Do you think we shall maintain start-time instead
    of failure-time for seq-sync worker as well? Or is there any other way
    to handle it?
    
    thanks
    Shveta
    
    
    
    
  256. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-07T10:00:04Z

    On Mon, Jul 7, 2025 at 2:37 PM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Fri, Jul 4, 2025 at 3:53 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Tue, 1 Jul 2025 at 15:20, shveta malik <shveta.malik@gmail.com> wrote:
    > > > On Mon, Jun 30, 2025 at 3:21 PM Nisha Moond <nisha.moond412@gmail.com> wrote:
    > > > >
    > > > > Please find the attached v20250630 patch set addressing above comments
    > > > > and other comments in [1],[2],[3] and [4].
    > > >
    > > > Thanks for the patches. I am still in process of reviewing it but
    > > > please find few comments:
    > > >
    > > > 1)
    > > > + if (pset.sversion >= 180000)
    > > > + appendPQExpBuffer(&buf,
    > > > +   ",\n  puballsequences AS \"%s\"",
    > > > +   gettext_noop("All sequences"));
    > > >
    > > > The server version check throughout the patch can be modified to 19000
    > > > as a new branch is created now.
    > >
    > > Modified
    > >
    > > > 2)
    > > > + bool all_pub; /* Special publication for all tables,
    > > > + * sequecnes */
    > > >
    > > > a) Typo: sequecnes --> sequences
    > >
    > > Modified
    > >
    > > > b) It is not clear from the comment that when will it be true? Will it
    > > > be set when either of all-tables or all-sequences is given or does it
    > > > need both?
    > >
    > > Updated the comments
    > >
    > > > 3)
    > > > postgres=# create publication pub1 for all sequences WITH ( PUBLISH='delete');
    > > > CREATE PUBLICATION
    > > > postgres=# create publication pub2 for all tables, sequences WITH
    > > > (PUBLISH='update');
    > > > CREATE PUBLICATION
    > > >
    > > > For the first command, 'WITH ( publication_parameter..' is useless.
    > > > For the second command, it is applicable only for 'all tables'.
    > > >
    > > > a) I am not sure if we even allow WITH in the first command?
    > > > b) In the second command, even if we allow it, there should be some
    > > > sort of NOTICE informing that it is applicable only to 'TABLES'.
    > > >
    > > > Thoughts?
    > > >
    > > > Also we allowed altering publication_parameter for all-sequences publication:
    > > >
    > > > postgres=# alter publication pub1 set (publish='insert,update');
    > > > ALTER PUBLICATION
    > > >
    > > > c) Should this be restricted as well? Thoughts?
    > >
    > > We have documented that the parameter of with clause is not applicable
    > > for sequences. I feel that all the above statements are ok with the
    > > documentation mentioned.
    > >
    > > Regarding the comments from [1].
    > > > 5)
    > > > In LogicalRepSyncSequences, why are we allocating it in a permanent
    > > > memory context?
    > > >
    > > > + /* Allocate the tracking info in a permanent memory context. */
    > > > + oldctx = MemoryContextSwitchTo(CacheMemoryContext);
    > > > + foreach_ptr(SubscriptionRelState, seq_state, sequences)
    > > > + {
    > > > + SubscriptionRelState *rstate = palloc(sizeof(SubscriptionRelState));
    > > > +
    > > > + memcpy(rstate, seq_state, sizeof(SubscriptionRelState));
    > > > + sequences_not_synced = lappend(sequences_not_synced, rstate);
    > > > + }
    > > > + MemoryContextSwitchTo(oldctx);
    > > >
    > > > Same for 'seq_info' allocation.
    > >
    > > When we are in between a transaction we will be using
    > > TopTransactionContext. We can palloc() in TopTransactionContext and
    > > safely use that memory throughout the transaction. But we cannot
    > > cannot access memory allocated in TopTransactionContext after
    > > CommitTransaction() finishes, because TopTransactionContext is
    > > explicitly reset (or deleted) at the end of the transaction.
    > > This is the reason we have to use CacheMemoryContext here.
    > >
    >
    > Okay. I see. Thanks for the details. Can we add this info in comments,
    > something like:
    > Allocate the tracking information in a permanent memory context to
    > ensure it remains accessible across multiple transactions during the
    > sequence copy process. The memory will be released once the copy is
    > finished.
    >
    > > The rest of the comments are fixed.
    >
    > Thank you for the patches. I am not done with review yet, but please
    > find the comments so far:
    >
    >
    > 1)
    > LogicalRepSyncSequences()
    >
    > + /* Allocate the sequences information in a permanent memory context. */
    > + oldctx = MemoryContextSwitchTo(CacheMemoryContext);
    > +
    > + /* Get the sequences that should be synchronized. */
    > + subsequences = GetSubscriptionRelations(subid, false, true, true);
    >
    > Here too we are using CacheMemoryContext? 'subsequences' is only used
    > in given function and not in copy_sequeneces. I guess, we start
    > multiple transactions in given function and thus make it essential to
    > allocate subsequences in CacheMemoryContext. But why are we doing
    > StartTransactionCommand twice? Is this intentional? Can we do it once
    > before GetSubscriptionRelations() and commit it once after for-loop is
    > over? IIUC, then we will not need CacheMemoryContext here.
    >
    > 2)
    > logicalrep_seqsyncworker_set_failuretime()
    >
    > a) This function is extern'ed in worker_internal.h. But I do not see
    > its usage outside launcher.c. Is it a mistake?
    >
    > b) Also, do we really need logicalrep_seqsyncworker_set_failuretime?
    > Is it better to move its logic instead in
    > logicalrep_seqsyncworker_set_failuretime()?
    >
    > 3)
    > SyncFetchRelationStates:
    > Earlier the name was FetchTableStates. If we really want to  use the
    > 'Sync' keyword, we can name it FetchRelationSyncStates, as we are
    > fetching sync-status only. Thoughts?
    >
    > 4)
    > ProcessSyncingSequencesForApply():
    > +
    > + if (rstate->state != SUBREL_STATE_INIT)
    > + continue;
    >
    > Why do we expect that rstate->state is not INIT at this time when we
    > have fetched only INIT sequences in sequence_states_not_ready. Shall
    > this be assert? If there is a valid scenario where it can be READY
    > here, please add comments.
    >
    > 5)
    > + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    > + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    > +    now, wal_retrieve_retry_interval))
    > + {
    > + MyLogicalRepWorker->sequencesync_failure_time = 0;
    > +
    > + logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    > + MyLogicalRepWorker->dbid,
    > + MySubscription->oid,
    > + MySubscription->name,
    > + MyLogicalRepWorker->userid,
    > + InvalidOid,
    > + DSM_HANDLE_INVALID);
    > + break;
    > + }
    >
    > We set sequencesync_failure_time to 0, but if logicalrep_worker_launch
    > is not able to launch the worker due to some reason, next time it will
    > not even wait for 'wal_retrieve_retry_interval time' to attempt
    > restarting it again. Is that intentional?
    >
    > In other workflows such as while launching table-sync or apply worker,
    >  this scenario does not arise. This is because we maintain start_time
    > there which can never be 0 instead of failure time and before
    > attempting to start the workers, we set start_time to current time.
    > The seq-sync failure-time OTOH is only set to non-null in
    > logicalrep_seqsyncworker_failure() and it is not necessary that we
    > will hit that function as the  logicalrep_worker_launch() may fail
    > before that itself. Do you think we shall maintain start-time instead
    > of failure-time for seq-sync worker as well? Or is there any other way
    > to handle it?
    >
    
    I thought about this more. Another idea could be to capture the return
    value of logicalrep_worker_launch() and if it is false, then we can
    set failure_time to current time. Thoughts?
    
    thanks
    Shveta
    
    
    
    
  257. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-09T08:42:35Z

    Please find a few more comments on July4 patch
    
    6)
    +  <para>
    +   To synchronize sequences from a publisher to a subscriber, first publish
    +   them using <link linkend="sql-createpublication-params-for-all-sequences">
    +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link>.
    +  </para>
    
    This sentence looks odd, as we have 'first' but no follow-up sentence
    after that. Can we please combine this line with the next one in the
    doc saying:
    
    To synchronize sequences from a publisher to a subscriber, first
    publish them using CREATE PUBLICATION ... FOR ALL SEQUENCES and then
    at the subscriber side:
    
    7)
    
    +         <para>
    +          This parameter is not applicable for sequences.
    +         </para>
    
    It is mentioned 3 times in doc for publish, publish_generated_columns
    and publish_via_partition_root. Instead shall we mention it once for
    WITH-clause itself. Something like:
    
    This clause specifies optional parameters for a publication when
    publishing tables. This clause is not applicable for sequences.
    
    8)
    +   The view <structname>pg_publication_sequences</structname> provides
    +   information about the mapping between publications and information of
    +   sequences they contain.
    
    Why not:
    "The view pg_publication_sequences provides information about the
    mapping between publications and sequences."
    
    I think the existing detail has been written similar to
    'pg_publication_tables' doc. But there, 'information of tables' made
    sense as pg_publication_tables has attnames and rowfilters  too. But
    pg_publication_sequences OTOH just has
    the mapping between names. No other information.
    
    9)
    +  <sect2 id="sequence-definition-mismatches">
    +   <title>Sequence Definition Mismatches</title>
    +   <warning>
    +    <para>
    +     During sequence synchronization, the sequence definitions of the publisher
    +     and the subscriber are compared.
    
    Now in code, we give WARNING for missing sequences on publisher as
    well. Do we need to mention that here? IIUC, this WARNING for missing
    sequences can come only if the worker is respawned to sync
    unmatched/failed sequences and meanwhile any one of failed sequences
    is dropped on publisher. But it will be good to mention it briefly in
    doc.
    
    
    thanks
    Shveta
    
    
    
    
  258. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-09T10:41:22Z

    On Mon, 7 Jul 2025 at 14:37, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > > When we are in between a transaction we will be using
    > > TopTransactionContext. We can palloc() in TopTransactionContext and
    > > safely use that memory throughout the transaction. But we cannot
    > > cannot access memory allocated in TopTransactionContext after
    > > CommitTransaction() finishes, because TopTransactionContext is
    > > explicitly reset (or deleted) at the end of the transaction.
    > > This is the reason we have to use CacheMemoryContext here.
    > >
    >
    > Okay. I see. Thanks for the details. Can we add this info in comments,
    > something like:
    > Allocate the tracking information in a permanent memory context to
    > ensure it remains accessible across multiple transactions during the
    > sequence copy process. The memory will be released once the copy is
    > finished.
    
    I felt the existing is ok as it is mentioned similarly in
    FetchRelationStates too. I don't want to keep it different in
    different places.
    
    > 1)
    > LogicalRepSyncSequences()
    >
    > + /* Allocate the sequences information in a permanent memory context. */
    > + oldctx = MemoryContextSwitchTo(CacheMemoryContext);
    > +
    > + /* Get the sequences that should be synchronized. */
    > + subsequences = GetSubscriptionRelations(subid, false, true, true);
    >
    > Here too we are using CacheMemoryContext? 'subsequences' is only used
    > in given function and not in copy_sequeneces. I guess, we start
    > multiple transactions in given function and thus make it essential to
    > allocate subsequences in CacheMemoryContext. But why are we doing
    > StartTransactionCommand twice? Is this intentional? Can we do it once
    > before GetSubscriptionRelations() and commit it once after for-loop is
    > over? IIUC, then we will not need CacheMemoryContext here.
    
    Modified
    
    > 2)
    > logicalrep_seqsyncworker_set_failuretime()
    >
    > a) This function is extern'ed in worker_internal.h. But I do not see
    > its usage outside launcher.c. Is it a mistake?
    
    This is removed now as part of the next comment fix
    
    > b) Also, do we really need logicalrep_seqsyncworker_set_failuretime?
    > Is it better to move its logic instead in
    > logicalrep_seqsyncworker_set_failuretime()?
    
    Modified
    
    > 3)
    > SyncFetchRelationStates:
    > Earlier the name was FetchTableStates. If we really want to  use the
    > 'Sync' keyword, we can name it FetchRelationSyncStates, as we are
    > fetching sync-status only. Thoughts?
    
    Instead of FetchRelationSyncStates, I preferred FetchRelationStates,
    and changed it to FetchRelationStates.
    
    > 4)
    > ProcessSyncingSequencesForApply():
    > +
    > + if (rstate->state != SUBREL_STATE_INIT)
    > + continue;
    >
    > Why do we expect that rstate->state is not INIT at this time when we
    > have fetched only INIT sequences in sequence_states_not_ready. Shall
    > this be assert? If there is a valid scenario where it can be READY
    > here, please add comments.
    
    Modified to Assert
    
    > 5)
    > + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    > + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    > +    now, wal_retrieve_retry_interval))
    > + {
    > + MyLogicalRepWorker->sequencesync_failure_time = 0;
    > +
    > + logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    > + MyLogicalRepWorker->dbid,
    > + MySubscription->oid,
    > + MySubscription->name,
    > + MyLogicalRepWorker->userid,
    > + InvalidOid,
    > + DSM_HANDLE_INVALID);
    > + break;
    > + }
    >
    > We set sequencesync_failure_time to 0, but if logicalrep_worker_launch
    > is not able to launch the worker due to some reason, next time it will
    > not even wait for 'wal_retrieve_retry_interval time' to attempt
    > restarting it again. Is that intentional?
    >
    > In other workflows such as while launching table-sync or apply worker,
    >  this scenario does not arise. This is because we maintain start_time
    > there which can never be 0 instead of failure time and before
    > attempting to start the workers, we set start_time to current time.
    > The seq-sync failure-time OTOH is only set to non-null in
    > logicalrep_seqsyncworker_failure() and it is not necessary that we
    > will hit that function as the  logicalrep_worker_launch() may fail
    > before that itself. Do you think we shall maintain start-time instead
    > of failure-time for seq-sync worker as well? Or is there any other way
    > to handle it?
    
    I preferred the suggestion from [1]. Modified it accordingly.
    
    The attached v20250709 version patch has the changes for the same.
    
    [1] - https://www.postgresql.org/message-id/CAJpy0uA6ugJN%2BtBwv38mG%2B6vf-uMuQoqxaZCX-mg1qBWX%2B%3DBkw%40mail.gmail.com
    
    Regards,
    Vignesh
    
  259. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-07-10T11:47:17Z

    On Wed, Jul 9, 2025 at 4:11 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > The attached v20250709 version patch has the changes for the same.
    >
    
    Thanks for the patches.
    
    In Patch-004: sequencesync.c : I think below function logic can be simplified.
    
    +void
    +ProcessSyncingSequencesForApply(void)
    +{
    + bool started_tx = false;
    +
    + Assert(!IsTransactionState());
    +
    + /* Start the sequencesync worker if needed, and there is not one already. */
    + foreach_ptr(SubscriptionRelState, rstate, sequence_states_not_ready)
    + {
    ...
    
    Currently, we loop through all INIT sequences to start a sequencesync
    worker. But since a single worker handles synchronization for all the
    sequences in list "sequence_states_not_ready", iterating through the
    entire list may lead to unnecessary work in cases like:
    
    a) when no sync worker slots are available (e.g., nsyncworkers ==
    max_sync_workers_per_subscription), or
    b) when sequencesync_failure_time hasn't yet elapsed.
    
    We could instead check if the list is non-empty (or use a simple bool)
    and attempt to start the worker. If it can’t be started, we can try
    again in the next apply loop.
    Thoughts?
    
    --
    Thanks.
    Nisha
    
    
    
    
  260. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-11T08:56:28Z

    On Wed, Jul 9, 2025 at 4:11 PM vignesh C <vignesh21@gmail.com> wrote:
    
    >
    > > 3)
    > > SyncFetchRelationStates:
    > > Earlier the name was FetchTableStates. If we really want to  use the
    > > 'Sync' keyword, we can name it FetchRelationSyncStates, as we are
    > > fetching sync-status only. Thoughts?
    >
    > Instead of FetchRelationSyncStates, I preferred FetchRelationStates,
    > and changed it to FetchRelationStates.
    >
    
    Okay, LGTM.
    
    > > 5)
    > > + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    > > + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    > > +    now, wal_retrieve_retry_interval))
    > > + {
    > > + MyLogicalRepWorker->sequencesync_failure_time = 0;
    > > +
    > > + logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    > > + MyLogicalRepWorker->dbid,
    > > + MySubscription->oid,
    > > + MySubscription->name,
    > > + MyLogicalRepWorker->userid,
    > > + InvalidOid,
    > > + DSM_HANDLE_INVALID);
    > > + break;
    > > + }
    > >
    > > We set sequencesync_failure_time to 0, but if logicalrep_worker_launch
    > > is not able to launch the worker due to some reason, next time it will
    > > not even wait for 'wal_retrieve_retry_interval time' to attempt
    > > restarting it again. Is that intentional?
    > >
    > > In other workflows such as while launching table-sync or apply worker,
    > >  this scenario does not arise. This is because we maintain start_time
    > > there which can never be 0 instead of failure time and before
    > > attempting to start the workers, we set start_time to current time.
    > > The seq-sync failure-time OTOH is only set to non-null in
    > > logicalrep_seqsyncworker_failure() and it is not necessary that we
    > > will hit that function as the  logicalrep_worker_launch() may fail
    > > before that itself. Do you think we shall maintain start-time instead
    > > of failure-time for seq-sync worker as well? Or is there any other way
    > > to handle it?
    >
    > I preferred the suggestion from [1]. Modified it accordingly.
    
    Okay, works for me.
    
    > The attached v20250709 version patch has the changes for the same.
    >
    
    Thank You for the patches. Please find a few comments:
    
    1)
    Shall we update pg_publication doc as well to indicate that pubinsert,
    pubupdate, pubdelete , pubtruncate, pubviaroot are meaningful only
    when publishing tables. For sequences, these have no meaning.
    
    2)
    Shall we have walrcv_disconnect() after copy is done in
    LogicalRepSyncSequences()
    
    3)
    Do we really need for-loop in ProcessSyncingSequencesForApply? I think
    this function is inspired from ProcessSyncingTablesForApply() but
    there we need different tablesync workers for different tables. For
    sequences, that is not the case and thus for-loop can be omitted. If
    we do so, we can amend the comments too where it says " Walk over all
    subscription sequences....."
    
    4)
    +# Confirm that the warning for parameters differing is logged.
    +$node_subscriber->wait_for_log(
    
    We can drop regress_seq_sub on the publisher now and check for missing
    warnings as the next step.
    
    
    5)
    I am revisiting the test given in [1], I see there is some document change as:
    
    +     Incremental sequence changes are not replicated.  Although the data in
    +     serial or identity columns backed by sequences will be replicated as part
    +     of the table, the sequences themselves do not replicate ongoing changes.
    +     On the subscriber, a sequence will retain the last value it synchronized
    +     from the publisher. If the subscriber is used as a read-only database,
    +     then this should typically not be a problem.  If, however, some kind of
    +     switchover or failover to the subscriber database is intended, then the
    +     sequences would need to be updated to the latest values, either by
    +     executing <link
    linkend="sql-altersubscription-params-refresh-publication-sequences">
    +     <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES</command></link>
    +     or by copying the current data from the publisher (perhaps using
    +     <command>pg_dump</command>) or by determining a sufficiently high value
    +     from the tables themselves.
    
    But this doc specifically mentions a failover case. It does not
    mention the case presented in [1] i.e. if user is trying to use
    sequence to populate identity column of a "subscribed" table where the
    sequence is also synced originally from publisher, then he may end up
    with corrupted state
    of IDENTITY column, and thus such cases should be used with caution.
    Please review once and see if we need to mention this and the example
    too.
    
    [1]: https://www.postgresql.org/message-id/CAJpy0uDK-QOULpd6x%2BisGrzwWyn16HHF0UPWqLGtOXQ-Z5M%3DyQ%40mail.gmail.com
    
    thanks
    Shveta
    
    
    
    
  261. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-11T09:26:39Z

    On Wed, 9 Jul 2025 at 14:12, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > Please find a few more comments on July4 patch
    >
    > 6)
    > +  <para>
    > +   To synchronize sequences from a publisher to a subscriber, first publish
    > +   them using <link linkend="sql-createpublication-params-for-all-sequences">
    > +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link>.
    > +  </para>
    >
    > This sentence looks odd, as we have 'first' but no follow-up sentence
    > after that. Can we please combine this line with the next one in the
    > doc saying:
    >
    > To synchronize sequences from a publisher to a subscriber, first
    > publish them using CREATE PUBLICATION ... FOR ALL SEQUENCES and then
    > at the subscriber side:
    
    Modified
    
    > 7)
    >
    > +         <para>
    > +          This parameter is not applicable for sequences.
    > +         </para>
    >
    > It is mentioned 3 times in doc for publish, publish_generated_columns
    > and publish_via_partition_root. Instead shall we mention it once for
    > WITH-clause itself. Something like:
    >
    > This clause specifies optional parameters for a publication when
    > publishing tables. This clause is not applicable for sequences.
    
    Modified
    
    > 8)
    > +   The view <structname>pg_publication_sequences</structname> provides
    > +   information about the mapping between publications and information of
    > +   sequences they contain.
    >
    > Why not:
    > "The view pg_publication_sequences provides information about the
    > mapping between publications and sequences."
    >
    > I think the existing detail has been written similar to
    > 'pg_publication_tables' doc. But there, 'information of tables' made
    > sense as pg_publication_tables has attnames and rowfilters  too. But
    > pg_publication_sequences OTOH just has
    > the mapping between names. No other information.
    
    Modified
    
    > 9)
    > +  <sect2 id="sequence-definition-mismatches">
    > +   <title>Sequence Definition Mismatches</title>
    > +   <warning>
    > +    <para>
    > +     During sequence synchronization, the sequence definitions of the publisher
    > +     and the subscriber are compared.
    >
    > Now in code, we give WARNING for missing sequences on publisher as
    > well. Do we need to mention that here? IIUC, this WARNING for missing
    > sequences can come only if the worker is respawned to sync
    > unmatched/failed sequences and meanwhile any one of failed sequences
    > is dropped on publisher. But it will be good to mention it briefly in
    > doc.
    
    Modified
    
    Also the comment from [1] is handled.
    The attached v20250711 version patch has the changes for the same.
    
    [1] - https://www.postgresql.org/message-id/CABdArM640YF7MQfMVhEX%3De1pJdrnVcCwS_y4XXsbvah%3D6P9S%3DA%40mail.gmail.com
    
    Regards,
    Vignesh
    
  262. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-14T04:33:25Z

    On Fri, 11 Jul 2025 at 14:26, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Wed, Jul 9, 2025 at 4:11 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > >
    > > > 3)
    > > > SyncFetchRelationStates:
    > > > Earlier the name was FetchTableStates. If we really want to  use the
    > > > 'Sync' keyword, we can name it FetchRelationSyncStates, as we are
    > > > fetching sync-status only. Thoughts?
    > >
    > > Instead of FetchRelationSyncStates, I preferred FetchRelationStates,
    > > and changed it to FetchRelationStates.
    > >
    >
    > Okay, LGTM.
    >
    > > > 5)
    > > > + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    > > > + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    > > > +    now, wal_retrieve_retry_interval))
    > > > + {
    > > > + MyLogicalRepWorker->sequencesync_failure_time = 0;
    > > > +
    > > > + logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    > > > + MyLogicalRepWorker->dbid,
    > > > + MySubscription->oid,
    > > > + MySubscription->name,
    > > > + MyLogicalRepWorker->userid,
    > > > + InvalidOid,
    > > > + DSM_HANDLE_INVALID);
    > > > + break;
    > > > + }
    > > >
    > > > We set sequencesync_failure_time to 0, but if logicalrep_worker_launch
    > > > is not able to launch the worker due to some reason, next time it will
    > > > not even wait for 'wal_retrieve_retry_interval time' to attempt
    > > > restarting it again. Is that intentional?
    > > >
    > > > In other workflows such as while launching table-sync or apply worker,
    > > >  this scenario does not arise. This is because we maintain start_time
    > > > there which can never be 0 instead of failure time and before
    > > > attempting to start the workers, we set start_time to current time.
    > > > The seq-sync failure-time OTOH is only set to non-null in
    > > > logicalrep_seqsyncworker_failure() and it is not necessary that we
    > > > will hit that function as the  logicalrep_worker_launch() may fail
    > > > before that itself. Do you think we shall maintain start-time instead
    > > > of failure-time for seq-sync worker as well? Or is there any other way
    > > > to handle it?
    > >
    > > I preferred the suggestion from [1]. Modified it accordingly.
    >
    > Okay, works for me.
    >
    > > The attached v20250709 version patch has the changes for the same.
    > >
    >
    > Thank You for the patches. Please find a few comments:
    >
    > 1)
    > Shall we update pg_publication doc as well to indicate that pubinsert,
    > pubupdate, pubdelete , pubtruncate, pubviaroot are meaningful only
    > when publishing tables. For sequences, these have no meaning.
    
    Since it is clearly mentioned it is for tables, I felt no need to
    mention again it is not applicable for sequences.
    
    > 2)
    > Shall we have walrcv_disconnect() after copy is done in
    > LogicalRepSyncSequences()
    
    There is a cleanup function registered for the worker to handle this
    at the worker exit. So this is not required.
    
    > 3)
    > Do we really need for-loop in ProcessSyncingSequencesForApply? I think
    > this function is inspired from ProcessSyncingTablesForApply() but
    > there we need different tablesync workers for different tables. For
    > sequences, that is not the case and thus for-loop can be omitted. If
    > we do so, we can amend the comments too where it says " Walk over all
    > subscription sequences....."
    
    Handled in the previous version
    
    > 4)
    > +# Confirm that the warning for parameters differing is logged.
    > +$node_subscriber->wait_for_log(
    >
    > We can drop regress_seq_sub on the publisher now and check for missing
    > warnings as the next step.
    
    Modified
    
    > 5)
    > I am revisiting the test given in [1], I see there is some document change as:
    >
    > +     Incremental sequence changes are not replicated.  Although the data in
    > +     serial or identity columns backed by sequences will be replicated as part
    > +     of the table, the sequences themselves do not replicate ongoing changes.
    > +     On the subscriber, a sequence will retain the last value it synchronized
    > +     from the publisher. If the subscriber is used as a read-only database,
    > +     then this should typically not be a problem.  If, however, some kind of
    > +     switchover or failover to the subscriber database is intended, then the
    > +     sequences would need to be updated to the latest values, either by
    > +     executing <link
    > linkend="sql-altersubscription-params-refresh-publication-sequences">
    > +     <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > SEQUENCES</command></link>
    > +     or by copying the current data from the publisher (perhaps using
    > +     <command>pg_dump</command>) or by determining a sufficiently high value
    > +     from the tables themselves.
    >
    > But this doc specifically mentions a failover case. It does not
    > mention the case presented in [1] i.e. if user is trying to use
    > sequence to populate identity column of a "subscribed" table where the
    > sequence is also synced originally from publisher, then he may end up
    > with corrupted state
    > of IDENTITY column, and thus such cases should be used with caution.
    > Please review once and see if we need to mention this and the example
    > too.
    
    In this case, the identity column data—as well as the non-identity
    columns—will be sent by the publisher as part of the row data. This
    behavior appears consistent with how non-sequence objects are handled
    in a publication.
    The following documentation note should be sufficient, as it already
    clarifies that "it will retain the last value it synchronized from the
    publisher":
    On the subscriber, a sequence will retain the last value it
    synchronized from the publisher. If the subscriber is used as a
    read-only database, this should typically not pose a problem.
    But if you have something in mind which should be added let me know.
    
    The attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  263. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-15T05:57:08Z

    On Mon, Jul 14, 2025 at 10:03 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 11 Jul 2025 at 14:26, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Wed, Jul 9, 2025 at 4:11 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > >
    > > > > 3)
    > > > > SyncFetchRelationStates:
    > > > > Earlier the name was FetchTableStates. If we really want to  use the
    > > > > 'Sync' keyword, we can name it FetchRelationSyncStates, as we are
    > > > > fetching sync-status only. Thoughts?
    > > >
    > > > Instead of FetchRelationSyncStates, I preferred FetchRelationStates,
    > > > and changed it to FetchRelationStates.
    > > >
    > >
    > > Okay, LGTM.
    > >
    > > > > 5)
    > > > > + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    > > > > + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    > > > > +    now, wal_retrieve_retry_interval))
    > > > > + {
    > > > > + MyLogicalRepWorker->sequencesync_failure_time = 0;
    > > > > +
    > > > > + logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    > > > > + MyLogicalRepWorker->dbid,
    > > > > + MySubscription->oid,
    > > > > + MySubscription->name,
    > > > > + MyLogicalRepWorker->userid,
    > > > > + InvalidOid,
    > > > > + DSM_HANDLE_INVALID);
    > > > > + break;
    > > > > + }
    > > > >
    > > > > We set sequencesync_failure_time to 0, but if logicalrep_worker_launch
    > > > > is not able to launch the worker due to some reason, next time it will
    > > > > not even wait for 'wal_retrieve_retry_interval time' to attempt
    > > > > restarting it again. Is that intentional?
    > > > >
    > > > > In other workflows such as while launching table-sync or apply worker,
    > > > >  this scenario does not arise. This is because we maintain start_time
    > > > > there which can never be 0 instead of failure time and before
    > > > > attempting to start the workers, we set start_time to current time.
    > > > > The seq-sync failure-time OTOH is only set to non-null in
    > > > > logicalrep_seqsyncworker_failure() and it is not necessary that we
    > > > > will hit that function as the  logicalrep_worker_launch() may fail
    > > > > before that itself. Do you think we shall maintain start-time instead
    > > > > of failure-time for seq-sync worker as well? Or is there any other way
    > > > > to handle it?
    > > >
    > > > I preferred the suggestion from [1]. Modified it accordingly.
    > >
    > > Okay, works for me.
    > >
    > > > The attached v20250709 version patch has the changes for the same.
    > > >
    > >
    > > Thank You for the patches. Please find a few comments:
    > >
    > > 1)
    > > Shall we update pg_publication doc as well to indicate that pubinsert,
    > > pubupdate, pubdelete , pubtruncate, pubviaroot are meaningful only
    > > when publishing tables. For sequences, these have no meaning.
    >
    > Since it is clearly mentioned it is for tables, I felt no need to
    > mention again it is not applicable for sequences.
    >
    > > 2)
    > > Shall we have walrcv_disconnect() after copy is done in
    > > LogicalRepSyncSequences()
    >
    > There is a cleanup function registered for the worker to handle this
    > at the worker exit. So this is not required.
    >
    > > 3)
    > > Do we really need for-loop in ProcessSyncingSequencesForApply? I think
    > > this function is inspired from ProcessSyncingTablesForApply() but
    > > there we need different tablesync workers for different tables. For
    > > sequences, that is not the case and thus for-loop can be omitted. If
    > > we do so, we can amend the comments too where it says " Walk over all
    > > subscription sequences....."
    >
    > Handled in the previous version
    >
    > > 4)
    > > +# Confirm that the warning for parameters differing is logged.
    > > +$node_subscriber->wait_for_log(
    > >
    > > We can drop regress_seq_sub on the publisher now and check for missing
    > > warnings as the next step.
    >
    > Modified
    >
    > > 5)
    > > I am revisiting the test given in [1], I see there is some document change as:
    > >
    > > +     Incremental sequence changes are not replicated.  Although the data in
    > > +     serial or identity columns backed by sequences will be replicated as part
    > > +     of the table, the sequences themselves do not replicate ongoing changes.
    > > +     On the subscriber, a sequence will retain the last value it synchronized
    > > +     from the publisher. If the subscriber is used as a read-only database,
    > > +     then this should typically not be a problem.  If, however, some kind of
    > > +     switchover or failover to the subscriber database is intended, then the
    > > +     sequences would need to be updated to the latest values, either by
    > > +     executing <link
    > > linkend="sql-altersubscription-params-refresh-publication-sequences">
    > > +     <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > > SEQUENCES</command></link>
    > > +     or by copying the current data from the publisher (perhaps using
    > > +     <command>pg_dump</command>) or by determining a sufficiently high value
    > > +     from the tables themselves.
    > >
    > > But this doc specifically mentions a failover case. It does not
    > > mention the case presented in [1] i.e. if user is trying to use
    > > sequence to populate identity column of a "subscribed" table where the
    > > sequence is also synced originally from publisher, then he may end up
    > > with corrupted state
    > > of IDENTITY column, and thus such cases should be used with caution.
    > > Please review once and see if we need to mention this and the example
    > > too.
    >
    > In this case, the identity column data—as well as the non-identity
    > columns—will be sent by the publisher as part of the row data. This
    > behavior appears consistent with how non-sequence objects are handled
    > in a publication.
    > The following documentation note should be sufficient, as it already
    > clarifies that "it will retain the last value it synchronized from the
    > publisher":
    
    Not very sure about it, but let me think more.
    
    > On the subscriber, a sequence will retain the last value it
    > synchronized from the publisher. If the subscriber is used as a
    > read-only database, this should typically not pose a problem.
    > But if you have something in mind which should be added let me know.
    
    Will let you know if I come up with something better to add here.
    
    > The attached patch has the changes for the same.
    
    Thank You. Few comments:
    
    1)
    patch 005 has trailing whitespaces issue.
    
    2)
    In LogicalRepSyncSequences(), do we really need this:
    
    + seq_count = list_length(subsequences);;
    
    seq_count is only used at the end to figure out if we really had some
    sequences. We can simply check subsequences against NIL for that
    purpose. If we really want to use list_length as a check, then we
    shall move it at  the end where we use it.
    
    3)
    LogicalRepSyncSequences():
    + MemoryContext oldctx;
    
    we can move this to a for-loop where it is being used.
    
    4)
    The only usage of  sequence_states_not_ready is this now:
    
    + /* No sequences to sync, so nothing to do */
    + if (list_length(sequence_states_not_ready) == 0)
    + return;
    
    Now, do we need to have it as a List?
    
    5)
    +  <sect2 id="missing-sequences">
    +   <title>Missing Sequences</title>
    +   <para>
    +    During sequence synchronization, if a sequence is dropped on the
    +    publisher. An ERROR is logged listing the missing sequences before the
    +    process exits. The apply worker detects this failure and repeatedly
    +    respawns the sequence synchronization worker to continue the
    +    synchronization process until the sequences are created in the publisher.
    +    See also <link
    linkend="guc-wal-retrieve-retry-interval"><varname>wal_retrieve_retry_interval</varname></link>.
    +   </para>
    +   <para>
    +    To resolve this, either use
    +    <link linkend="sql-createsequence"><command>CREATE
    SEQUENCE</command></link>
    +    to recreate the missing sequence on the publisher, or, if the sequence are
    +    no longer required, execute <link
    linkend="sql-altersubscription-params-refresh-publication">
    +    <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</command></link>
    +    to remove the stale sequence entries from synchronization in the
    subscriber.
    +   </para>
    +  </sect2>
    +
    
    Please see if this looks appropriate, I have added drop-sequence
    option as well and corrected few trivial things:
    
    During sequence synchronization, if a sequence is dropped on the
    publisher, an ERROR is logged listing the missing sequences before the
    process exits. The apply worker detects this failure and repeatedly
    respawns the sequence synchronization worker to continue the
    synchronization process until the sequences are either recreated on
    the publisher, dropped on the subscriber, or removed from the
    synchronization list.
    
    To resolve this issue, either recreate the missing sequence on the
    publisher using CREATE SEQUENCE, drop the sequences on the subscriber
    if they are no longer needed using DROP SEQUENCE, or run ALTER
    SUBSCRIPTION ... REFRESH PUBLICATION to remove these sequences from
    synchronization on the subscriber.
    
    thanks
    Shveta
    
    
    
    
  264. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-07-16T05:44:44Z

    On Mon, Jul 14, 2025 at 10:03 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 11 Jul 2025 at 14:26, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    I have picked this up again for final review, started with 0001, I
    think mostly 0001 looks good to me, except few comments
    
    1.
    + lsn = PageGetLSN(page);
    + last_value = seq->last_value;
    + log_cnt = seq->log_cnt;
    + is_called = seq->is_called;
    +
    + UnlockReleaseBuffer(buf);
    + sequence_close(seqrel, NoLock);
    +
    + /* Page LSN for the sequence */
    + values[0] = LSNGetDatum(lsn);
    +
    + /* The value most recently returned by nextval in the current session */
    + values[1] = Int64GetDatum(last_value);
    +
    
    I think we can avoid using extra variables like lsn, last_value etc
    instead we can directly copy into the value[$] as shown below.
    
    values[0] = LSNGetDatum(PageGetLSN(page));
    values[1] = Int64GetDatum(seq->last_value);
    ...
    UnlockReleaseBuffer(buf);
    sequence_close(seqrel, NoLock);
    
    2.
    +       <para>
    +        Returns information about the sequence. <literal>page_lsn</literal> is
    +        the page LSN of the sequence, <literal>last_value</literal> is the
    +        current value of the sequence, <literal>log_cnt</literal> shows how
    +        many fetches remain before a new WAL record must be written, and
    +        <literal>is_called</literal> indicates whether the sequence has been
    +        used.
    
    Shall we change 'is the page LSN of the sequence' to 'is the page LSN
    of the sequence relation'
    
    And I think this field doesn't seem to be very relevant for the user,
    although we are exposing it because we need it for internal use.
    Maybe at least the commit message of this patch should give some
    details on why we need to expose this field.
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  265. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-16T06:51:08Z

    On Tue, 15 Jul 2025 at 11:27, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > Thank You. Few comments:
    >
    > 1)
    > patch 005 has trailing whitespaces issue.
    
    Fixed them
    
    > 2)
    > In LogicalRepSyncSequences(), do we really need this:
    >
    > + seq_count = list_length(subsequences);;
    >
    > seq_count is only used at the end to figure out if we really had some
    > sequences. We can simply check subsequences against NIL for that
    > purpose. If we really want to use list_length as a check, then we
    > shall move it at  the end where we use it.
    
    Modified
    
    > 3)
    > LogicalRepSyncSequences():
    > + MemoryContext oldctx;
    >
    > we can move this to a for-loop where it is being used.
    
    Modified
    
    > 4)
    > The only usage of  sequence_states_not_ready is this now:
    >
    > + /* No sequences to sync, so nothing to do */
    > + if (list_length(sequence_states_not_ready) == 0)
    > + return;
    >
    > Now, do we need to have it as a List?
    
    Removed this list variable and used a output function argument in
    FetchRelationStates
    
    > 5)
    > +  <sect2 id="missing-sequences">
    > +   <title>Missing Sequences</title>
    > +   <para>
    > +    During sequence synchronization, if a sequence is dropped on the
    > +    publisher. An ERROR is logged listing the missing sequences before the
    > +    process exits. The apply worker detects this failure and repeatedly
    > +    respawns the sequence synchronization worker to continue the
    > +    synchronization process until the sequences are created in the publisher.
    > +    See also <link
    > linkend="guc-wal-retrieve-retry-interval"><varname>wal_retrieve_retry_interval</varname></link>.
    > +   </para>
    > +   <para>
    > +    To resolve this, either use
    > +    <link linkend="sql-createsequence"><command>CREATE
    > SEQUENCE</command></link>
    > +    to recreate the missing sequence on the publisher, or, if the sequence are
    > +    no longer required, execute <link
    > linkend="sql-altersubscription-params-refresh-publication">
    > +    <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</command></link>
    > +    to remove the stale sequence entries from synchronization in the
    > subscriber.
    > +   </para>
    > +  </sect2>
    > +
    >
    > Please see if this looks appropriate, I have added drop-sequence
    > option as well and corrected few trivial things:
    >
    > During sequence synchronization, if a sequence is dropped on the
    > publisher, an ERROR is logged listing the missing sequences before the
    > process exits. The apply worker detects this failure and repeatedly
    > respawns the sequence synchronization worker to continue the
    > synchronization process until the sequences are either recreated on
    > the publisher, dropped on the subscriber, or removed from the
    > synchronization list.
    >
    > To resolve this issue, either recreate the missing sequence on the
    > publisher using CREATE SEQUENCE, drop the sequences on the subscriber
    > if they are no longer needed using DROP SEQUENCE, or run ALTER
    > SUBSCRIPTION ... REFRESH PUBLICATION to remove these sequences from
    > synchronization on the subscriber.
    
    Modified
    
    The attached v20250716 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  266. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-17T11:21:53Z

    On Wed, 16 Jul 2025 at 11:15, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Mon, Jul 14, 2025 at 10:03 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Fri, 11 Jul 2025 at 14:26, shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > I have picked this up again for final review, started with 0001, I
    > think mostly 0001 looks good to me, except few comments
    >
    > 1.
    > + lsn = PageGetLSN(page);
    > + last_value = seq->last_value;
    > + log_cnt = seq->log_cnt;
    > + is_called = seq->is_called;
    > +
    > + UnlockReleaseBuffer(buf);
    > + sequence_close(seqrel, NoLock);
    > +
    > + /* Page LSN for the sequence */
    > + values[0] = LSNGetDatum(lsn);
    > +
    > + /* The value most recently returned by nextval in the current session */
    > + values[1] = Int64GetDatum(last_value);
    > +
    >
    > I think we can avoid using extra variables like lsn, last_value etc
    > instead we can directly copy into the value[$] as shown below.
    >
    > values[0] = LSNGetDatum(PageGetLSN(page));
    > values[1] = Int64GetDatum(seq->last_value);
    > ...
    > UnlockReleaseBuffer(buf);
    > sequence_close(seqrel, NoLock);
    
    Modified
    
    > 2.
    > +       <para>
    > +        Returns information about the sequence. <literal>page_lsn</literal> is
    > +        the page LSN of the sequence, <literal>last_value</literal> is the
    > +        current value of the sequence, <literal>log_cnt</literal> shows how
    > +        many fetches remain before a new WAL record must be written, and
    > +        <literal>is_called</literal> indicates whether the sequence has been
    > +        used.
    >
    > Shall we change 'is the page LSN of the sequence' to 'is the page LSN
    > of the sequence relation'
    
    Modified
    
    > And I think this field doesn't seem to be very relevant for the user,
    > although we are exposing it because we need it for internal use.
    > Maybe at least the commit message of this patch should give some
    > details on why we need to expose this field.
    
    Updated commit message
    
    The attached v20250717 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  267. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-07-18T05:14:30Z

    On Thu, Jul 17, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 16 Jul 2025 at 11:15, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Mon, Jul 14, 2025 at 10:03 AM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Fri, 11 Jul 2025 at 14:26, shveta malik <shveta.malik@gmail.com> wrote:
    > > > >
    > > I have picked this up again for final review, started with 0001, I
    > > think mostly 0001 looks good to me, except few comments
    > >
    > > 1.
    > > + lsn = PageGetLSN(page);
    > > + last_value = seq->last_value;
    > > + log_cnt = seq->log_cnt;
    > > + is_called = seq->is_called;
    > > +
    > > + UnlockReleaseBuffer(buf);
    > > + sequence_close(seqrel, NoLock);
    > > +
    > > + /* Page LSN for the sequence */
    > > + values[0] = LSNGetDatum(lsn);
    > > +
    > > + /* The value most recently returned by nextval in the current session */
    > > + values[1] = Int64GetDatum(last_value);
    > > +
    > >
    > > I think we can avoid using extra variables like lsn, last_value etc
    > > instead we can directly copy into the value[$] as shown below.
    > >
    > > values[0] = LSNGetDatum(PageGetLSN(page));
    > > values[1] = Int64GetDatum(seq->last_value);
    > > ...
    > > UnlockReleaseBuffer(buf);
    > > sequence_close(seqrel, NoLock);
    >
    > Modified
    >
    > > 2.
    > > +       <para>
    > > +        Returns information about the sequence. <literal>page_lsn</literal> is
    > > +        the page LSN of the sequence, <literal>last_value</literal> is the
    > > +        current value of the sequence, <literal>log_cnt</literal> shows how
    > > +        many fetches remain before a new WAL record must be written, and
    > > +        <literal>is_called</literal> indicates whether the sequence has been
    > > +        used.
    > >
    > > Shall we change 'is the page LSN of the sequence' to 'is the page LSN
    > > of the sequence relation'
    >
    > Modified
    >
    > > And I think this field doesn't seem to be very relevant for the user,
    > > although we are exposing it because we need it for internal use.
    > > Maybe at least the commit message of this patch should give some
    > > details on why we need to expose this field.
    >
    > Updated commit message
    >
    > The attached v20250717 version patch has the changes for the same.
    
    Thanks, 0001 looks fine after this, I will share the feedback for other patches.
    
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  268. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-07-18T08:40:58Z

    On Fri, Jul 18, 2025 at 10:44 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Thu, Jul 17, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    
    I was looking at the high level idea of sequence sync worker patch
    i.e. 0005, so far I haven't found anything problematic there, but I
    haven't completed the review and testing yet.  Here are some comments
    I have while reading through the patch.  I will try to do more
    thorough review and testing next week.
    
    1.
    + /*
    + * Count running sync workers for this subscription, while we have the
    + * lock.
    + */
    + nsyncworkers = logicalrep_sync_worker_count(MyLogicalRepWorker->subid);
    +
    + /* Now safe to release the LWLock */
    + LWLockRelease(LogicalRepWorkerLock);
    +
    + /*
    + * If there is a free sync worker slot, start a new sequencesync worker,
    + * and break from the loop.
    + */
    + if (nsyncworkers < max_sync_workers_per_subscription)
    + {
    + TimestampTz now = GetCurrentTimestamp();
    +
    + /*
    + * To prevent starting the sequencesync worker at a high frequency
    + * after a failure, we store its last failure time. We start the
    + * sequencesync worker again after waiting at least
    + * wal_retrieve_retry_interval.
    + */
    + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    +    now, wal_retrieve_retry_interval))
    + {
    + MyLogicalRepWorker->sequencesync_failure_time = 0;
    +
    + if (!logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    +   MyLogicalRepWorker->dbid,
    +   MySubscription->oid,
    +   MySubscription->name,
    +   MyLogicalRepWorker->userid,
    +   InvalidOid,
    +   DSM_HANDLE_INVALID))
    + MyLogicalRepWorker->sequencesync_failure_time = now;
    + }
    
    This code seems to duplicate much of the logic found in
    ProcessSyncingTablesForApply() within its final else block, with only
    minor differences (perhaps 1-2 lines).
    
    To improve code maintainability and avoid redundancy, consider
    extracting the common logic into a static function. This function
    could then be called from both places.
    
    2.
    +/*
    + * Common function to setup the leader apply, tablesync worker and sequencesync
    + * worker.
    + */
    
    Change to "Common function to setup the leader apply, tablesync and
    sequencesync worker"
    
    3.
    + /*
    + * To prevent starting the sequencesync worker at a high frequency
    + * after a failure, we store its last failure time. We start the
    + * sequencesync worker again after waiting at least
    + * wal_retrieve_retry_interval.
    + */
    
    We haven't explained what's the rationale behind comparing with the
    last failure time for sequence sync worker whereas for table sync
    worker we compare with last start time.
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  269. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-07-18T10:45:06Z

    On Thu, Jul 17, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > The attached v20250717 version patch has the changes for the same.
    >
    
    Few comments on 0001 and 0002:
    0001
    1. Instead of introducing a new function, can we think of extending
    the existing function pg_get_sequence_data()?
    
    0002
    2.
    postgres=# Create publication pub2 for all tables, sequences;
    CREATE PUBLICATION
    ...
    postgres=# Create publication pub3 for all tables, all sequences;
    ERROR:  syntax error at or near "all"
    LINE 1: Create publication pub3 for all tables, all sequences;
    
    I was expecting first syntax to give ERROR and second to work. I have
    given this comment in my earlier email[1]. I see a follow up response
    by Nisha indicating that she agreed with it [2]. By any chance, did
    you people misunderstood and implemented the reverse of what I asked?
    
    3.
    postgres=> Create publication pub3 for all tables, sequences;
    ERROR:  must be superuser to create a FOR ALL TABLES publication
    
    In the above, the publication is both FOR ALL TABLES and ALL
    SEQUENCES. Won't it be better to give a message like: "must be
    superuser to create a FOR ALL TABLES OR ALL SEQUENCES publication"? I
    think we can give this same message in cases where publication is (a)
    FOR ALL TABLES, (b) FOR ALL SEQUENCES, or (c) FOR ALL TABLES,
    SEQUENCES.
    
    Whatever we decide here, we can follow that in other parts of the
    patch (where applicable) as well. For example, one case is as below:
    + if (!superuser_arg(newOwnerId))
    + {
    + if (form->puballtables)
    + ereport(ERROR,
    + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    + errmsg("permission denied to change owner of publication \"%s\"",
    +    NameStr(form->pubname)),
    + errhint("The owner of a FOR ALL TABLES publication must be a superuser."));
    + if (form->puballsequences)
    + ereport(ERROR,
    + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    + errmsg("permission denied to change owner of publication \"%s\"",
    +    NameStr(form->pubname)),
    + errhint("The owner of a FOR ALL SEQUENCES publication must be a superuser."));
    
    [1]:  https://www.postgresql.org/message-id/CAA4eK1%2B6L%2BAoGS3LHdnYnCE%3DnRHergSQyhyO7Y%3D-sOp7isGVMw%40mail.gmail.com
    [2]: https://www.postgresql.org/message-id/CABdArM52CSDuYsfTAEp4ZSWe%2BGFBvxgnPFgkG%2Bid9T88DUE%2B1Q%40mail.gmail.com
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  270. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-20T14:15:13Z

    On Fri, 18 Jul 2025 at 16:15, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Jul 17, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached v20250717 version patch has the changes for the same.
    > >
    >
    > Few comments on 0001 and 0002:
    > 0001
    > 1. Instead of introducing a new function, can we think of extending
    > the existing function pg_get_sequence_data()?
    
    Yes, this can be extended. Modified.
    
    > 0002
    > 2.
    > postgres=# Create publication pub2 for all tables, sequences;
    > CREATE PUBLICATION
    > ...
    > postgres=# Create publication pub3 for all tables, all sequences;
    > ERROR:  syntax error at or near "all"
    > LINE 1: Create publication pub3 for all tables, all sequences;
    >
    > I was expecting first syntax to give ERROR and second to work. I have
    > given this comment in my earlier email[1]. I see a follow up response
    > by Nisha indicating that she agreed with it [2]. By any chance, did
    > you people misunderstood and implemented the reverse of what I asked?
    
    This was a misunderstanding here. Updated accordingly.
    
    > 3.
    > postgres=> Create publication pub3 for all tables, sequences;
    > ERROR:  must be superuser to create a FOR ALL TABLES publication
    >
    > In the above, the publication is both FOR ALL TABLES and ALL
    > SEQUENCES. Won't it be better to give a message like: "must be
    > superuser to create a FOR ALL TABLES OR ALL SEQUENCES publication"? I
    > think we can give this same message in cases where publication is (a)
    > FOR ALL TABLES, (b) FOR ALL SEQUENCES, or (c) FOR ALL TABLES,
    > SEQUENCES.
    
    Modified
    
    > Whatever we decide here, we can follow that in other parts of the
    > patch (where applicable) as well. For example, one case is as below:
    > + if (!superuser_arg(newOwnerId))
    > + {
    > + if (form->puballtables)
    > + ereport(ERROR,
    > + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    > + errmsg("permission denied to change owner of publication \"%s\"",
    > +    NameStr(form->pubname)),
    > + errhint("The owner of a FOR ALL TABLES publication must be a superuser."));
    > + if (form->puballsequences)
    > + ereport(ERROR,
    > + errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
    > + errmsg("permission denied to change owner of publication \"%s\"",
    > +    NameStr(form->pubname)),
    > + errhint("The owner of a FOR ALL SEQUENCES publication must be a superuser."));
    
    Modified here too.
    
    The attached v20250720 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  271. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-20T14:18:42Z

    On Fri, 18 Jul 2025 at 14:11, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Fri, Jul 18, 2025 at 10:44 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Thu, Jul 17, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    >
    > I was looking at the high level idea of sequence sync worker patch
    > i.e. 0005, so far I haven't found anything problematic there, but I
    > haven't completed the review and testing yet.  Here are some comments
    > I have while reading through the patch.  I will try to do more
    > thorough review and testing next week.
    >
    > 1.
    > + /*
    > + * Count running sync workers for this subscription, while we have the
    > + * lock.
    > + */
    > + nsyncworkers = logicalrep_sync_worker_count(MyLogicalRepWorker->subid);
    > +
    > + /* Now safe to release the LWLock */
    > + LWLockRelease(LogicalRepWorkerLock);
    > +
    > + /*
    > + * If there is a free sync worker slot, start a new sequencesync worker,
    > + * and break from the loop.
    > + */
    > + if (nsyncworkers < max_sync_workers_per_subscription)
    > + {
    > + TimestampTz now = GetCurrentTimestamp();
    > +
    > + /*
    > + * To prevent starting the sequencesync worker at a high frequency
    > + * after a failure, we store its last failure time. We start the
    > + * sequencesync worker again after waiting at least
    > + * wal_retrieve_retry_interval.
    > + */
    > + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    > + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    > +    now, wal_retrieve_retry_interval))
    > + {
    > + MyLogicalRepWorker->sequencesync_failure_time = 0;
    > +
    > + if (!logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    > +   MyLogicalRepWorker->dbid,
    > +   MySubscription->oid,
    > +   MySubscription->name,
    > +   MyLogicalRepWorker->userid,
    > +   InvalidOid,
    > +   DSM_HANDLE_INVALID))
    > + MyLogicalRepWorker->sequencesync_failure_time = now;
    > + }
    >
    > This code seems to duplicate much of the logic found in
    > ProcessSyncingTablesForApply() within its final else block, with only
    > minor differences (perhaps 1-2 lines).
    >
    > To improve code maintainability and avoid redundancy, consider
    > extracting the common logic into a static function. This function
    > could then be called from both places.
    
    Modified
    
    > 2.
    > +/*
    > + * Common function to setup the leader apply, tablesync worker and sequencesync
    > + * worker.
    > + */
    >
    > Change to "Common function to setup the leader apply, tablesync and
    > sequencesync worker"
    
    Modified
    
    > 3.
    > + /*
    > + * To prevent starting the sequencesync worker at a high frequency
    > + * after a failure, we store its last failure time. We start the
    > + * sequencesync worker again after waiting at least
    > + * wal_retrieve_retry_interval.
    > + */
    >
    > We haven't explained what's the rationale behind comparing with the
    > last failure time for sequence sync worker whereas for table sync
    > worker we compare with last start time.
    
    Since we use a single sequencesync worker to handle all sequence
    synchronization, I considered marking a failure when the worker exits
    and using that as a trigger for retries. However, since tablesync
    relies on the start time for retries, it would be more consistent to
    apply the same approach here.
    
    The v20250720 version patch attached at [1] has the changes for the same.
    [1] - https://www.postgresql.org/message-id/CALDaNm2swnY6nYAg%3D%3D7-4ah3yyaBQ_5wyr57p%3D%2BvtpfuSOT%2Bag%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  272. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-07-21T05:06:32Z

    On Sun, Jul 20, 2025 at 7:48 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 18 Jul 2025 at 14:11, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Fri, Jul 18, 2025 at 10:44 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > >
    > > > On Thu, Jul 17, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > >
    > > I was looking at the high level idea of sequence sync worker patch
    > > i.e. 0005, so far I haven't found anything problematic there, but I
    > > haven't completed the review and testing yet.  Here are some comments
    > > I have while reading through the patch.  I will try to do more
    > > thorough review and testing next week.
    > >
    > > 1.
    > > + /*
    > > + * Count running sync workers for this subscription, while we have the
    > > + * lock.
    > > + */
    > > + nsyncworkers = logicalrep_sync_worker_count(MyLogicalRepWorker->subid);
    > > +
    > > + /* Now safe to release the LWLock */
    > > + LWLockRelease(LogicalRepWorkerLock);
    > > +
    > > + /*
    > > + * If there is a free sync worker slot, start a new sequencesync worker,
    > > + * and break from the loop.
    > > + */
    > > + if (nsyncworkers < max_sync_workers_per_subscription)
    > > + {
    > > + TimestampTz now = GetCurrentTimestamp();
    > > +
    > > + /*
    > > + * To prevent starting the sequencesync worker at a high frequency
    > > + * after a failure, we store its last failure time. We start the
    > > + * sequencesync worker again after waiting at least
    > > + * wal_retrieve_retry_interval.
    > > + */
    > > + if (!MyLogicalRepWorker->sequencesync_failure_time ||
    > > + TimestampDifferenceExceeds(MyLogicalRepWorker->sequencesync_failure_time,
    > > +    now, wal_retrieve_retry_interval))
    > > + {
    > > + MyLogicalRepWorker->sequencesync_failure_time = 0;
    > > +
    > > + if (!logicalrep_worker_launch(WORKERTYPE_SEQUENCESYNC,
    > > +   MyLogicalRepWorker->dbid,
    > > +   MySubscription->oid,
    > > +   MySubscription->name,
    > > +   MyLogicalRepWorker->userid,
    > > +   InvalidOid,
    > > +   DSM_HANDLE_INVALID))
    > > + MyLogicalRepWorker->sequencesync_failure_time = now;
    > > + }
    > >
    > > This code seems to duplicate much of the logic found in
    > > ProcessSyncingTablesForApply() within its final else block, with only
    > > minor differences (perhaps 1-2 lines).
    > >
    > > To improve code maintainability and avoid redundancy, consider
    > > extracting the common logic into a static function. This function
    > > could then be called from both places.
    >
    > Modified
    >
    > > 2.
    > > +/*
    > > + * Common function to setup the leader apply, tablesync worker and sequencesync
    > > + * worker.
    > > + */
    > >
    > > Change to "Common function to setup the leader apply, tablesync and
    > > sequencesync worker"
    >
    > Modified
    >
    > > 3.
    > > + /*
    > > + * To prevent starting the sequencesync worker at a high frequency
    > > + * after a failure, we store its last failure time. We start the
    > > + * sequencesync worker again after waiting at least
    > > + * wal_retrieve_retry_interval.
    > > + */
    > >
    > > We haven't explained what's the rationale behind comparing with the
    > > last failure time for sequence sync worker whereas for table sync
    > > worker we compare with last start time.
    >
    > Since we use a single sequencesync worker to handle all sequence
    > synchronization, I considered marking a failure when the worker exits
    > and using that as a trigger for retries. However, since tablesync
    > relies on the start time for retries, it would be more consistent to
    > apply the same approach here.
    >
    > The v20250720 version patch attached at [1] has the changes for the same.
    > [1] - https://www.postgresql.org/message-id/CALDaNm2swnY6nYAg%3D%3D7-4ah3yyaBQ_5wyr57p%3D%2BvtpfuSOT%2Bag%40mail.gmail.com
    
    I was just trying a different test, so I realized that ALTER
    PUBLICATION ADD SEQUENCE is not supported, any reason for the same?
    
    postgres[154731]=# ALTER PUBLICATION pub ADD sequence s1;
    ERROR:  42601: invalid publication object list
    LINE 1: ALTER PUBLICATION pub ADD sequence s1;
    DETAIL:  One of TABLE or TABLES IN SCHEMA must be specified before a
    standalone table or schema name.
    LOCATION:  preprocess_pubobj_list, gram.y:19685
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  273. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-07-21T05:45:33Z

    On Mon, Jul 21, 2025 at 10:36 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > I was just trying a different test, so I realized that ALTER
    > PUBLICATION ADD SEQUENCE is not supported, any reason for the same?
    >
    > postgres[154731]=# ALTER PUBLICATION pub ADD sequence s1;
    > ERROR:  42601: invalid publication object list
    > LINE 1: ALTER PUBLICATION pub ADD sequence s1;
    > DETAIL:  One of TABLE or TABLES IN SCHEMA must be specified before a
    > standalone table or schema name.
    > LOCATION:  preprocess_pubobj_list, gram.y:19685
    >
    Also I noticed that
    1. We don't allow creating publication with individual sequences (e.g.
    CREATE PUBLICATION pub FOR SEQUENCE s1;).  Is it because the main
    purpose of this sync is major version upgrade and we do not have
    scenarios for replicating a few sequences or there are some technical
    difficulties in achieving that or both.
    
    2. This syntax works (CREATE PUBLICATION pub FOR ALL TABLES,
    SEQUENCES;) but tab completion doesn't suggest this
    
    3. Some of the syntaxes works for sequence which doesn't make sense to
    me, as listed below, I think there are more
    
    postgres[154731]=# CREATE PUBLICATION insert_only FOR ALL SEQUENCES
    WITH (publish = 'insert');
    CREATE PUBLICATION
    
    postgres[154731]=# CREATE PUBLICATION pub FOR ALL SEQUENCES WITH (
    PUBLISH_VIA_PARTITION_ROOT );
    CREATE PUBLICATION
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  274. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-21T06:47:13Z

    On Mon, Jul 21, 2025 at 11:15 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > 3. Some of the syntaxes works for sequence which doesn't make sense to
    > me, as listed below, I think there are more
    >
    > postgres[154731]=# CREATE PUBLICATION insert_only FOR ALL SEQUENCES
    > WITH (publish = 'insert');
    > CREATE PUBLICATION
    >
    > postgres[154731]=# CREATE PUBLICATION pub FOR ALL SEQUENCES WITH (
    > PUBLISH_VIA_PARTITION_ROOT );
    > CREATE PUBLICATION
    
    +1. I had the same concerns at [1]. It might be feasible to restrict
    this if we have CREATE SUB for ALL SEQ alone. But if we have ALL
    SEQUENCES and ALL TABLES together, then 'WITH'  makes sense for tables
    but not for sequences. My suggestion earlier was to display a NOTICE
    at-least to say that WITH is not applicable to SEQUENCES (in case we
    can not restrict it).
    
    [1]: https://www.postgresql.org/message-id/CAJpy0uBFXJLOiFOL8QgSeS93Bf%3DZQd86BXZa%3DMeijHQo-%3Da2cA%40mail.gmail.com
    
    thanks
    Shveta
    
    
    
    
  275. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-21T08:52:53Z

    On Mon, 21 Jul 2025 at 10:36, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > I was just trying a different test, so I realized that ALTER
    > PUBLICATION ADD SEQUENCE is not supported, any reason for the same?
    >
    > postgres[154731]=# ALTER PUBLICATION pub ADD sequence s1;
    > ERROR:  42601: invalid publication object list
    > LINE 1: ALTER PUBLICATION pub ADD sequence s1;
    > DETAIL:  One of TABLE or TABLES IN SCHEMA must be specified before a
    > standalone table or schema name.
    > LOCATION:  preprocess_pubobj_list, gram.y:19685
    
    I have intentionally left this out for now. Once the current patch is
    committed, we can extend it.
    
    Regards,
    Vignesh
    
    
    
    
  276. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-21T09:06:32Z

    On Mon, 21 Jul 2025 at 11:15, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Mon, Jul 21, 2025 at 10:36 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > I was just trying a different test, so I realized that ALTER
    > > PUBLICATION ADD SEQUENCE is not supported, any reason for the same?
    > >
    > > postgres[154731]=# ALTER PUBLICATION pub ADD sequence s1;
    > > ERROR:  42601: invalid publication object list
    > > LINE 1: ALTER PUBLICATION pub ADD sequence s1;
    > > DETAIL:  One of TABLE or TABLES IN SCHEMA must be specified before a
    > > standalone table or schema name.
    > > LOCATION:  preprocess_pubobj_list, gram.y:19685
    > >
    > Also I noticed that
    > 1. We don't allow creating publication with individual sequences (e.g.
    > CREATE PUBLICATION pub FOR SEQUENCE s1;).  Is it because the main
    > purpose of this sync is major version upgrade and we do not have
    > scenarios for replicating a few sequences or there are some technical
    > difficulties in achieving that or both.
    
    There are no technical difficulties here. The main goal was to support
    all sequences necessary for the upgrade scenario. Once that is
    complete, the implementation can be extended based on additional use
    cases.
    
    > 2. This syntax works (CREATE PUBLICATION pub FOR ALL TABLES,
    > SEQUENCES;) but tab completion doesn't suggest this
    
    Nisha had analysed this and shared this  earlier at [1]:
    Tab-completion is not supported after a comma (,) in any other cases.
    For example, the following commands are valid, but tab-completion does
    not work after the comma:
    CREATE PUBLICATION pub7 FOR TABLE t1, TABLES IN SCHEMA public;
    CREATE PUBLICATION pub7 FOR TABLES IN SCHEMA public, TABLES IN SCHEMA schema2;
    
    > 3. Some of the syntaxes works for sequence which doesn't make sense to
    > me, as listed below, I think there are more
    >
    > postgres[154731]=# CREATE PUBLICATION insert_only FOR ALL SEQUENCES
    > WITH (publish = 'insert');
    > CREATE PUBLICATION
    >
    > postgres[154731]=# CREATE PUBLICATION pub FOR ALL SEQUENCES WITH (
    > PUBLISH_VIA_PARTITION_ROOT );
    > CREATE PUBLICATION
    
    There is a documentation for this at sql-createpublication.html:
    WITH ( publication_parameter [= value] [, ... ] )
        This clause specifies optional parameters for a publication when
    publishing tables. This clause is not applicable for sequences.
    
    I felt it was enough, should we do anything more here?
    
    [1] - https://www.postgresql.org/message-id/CABdArM5axwoTorZnJww5rE79SNzvnnXCfWkv7XJex1Rkz%3DJDog%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  277. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-07-21T09:25:38Z

    On Mon, Jul 21, 2025 at 2:36 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 21 Jul 2025 at 11:15, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    >
    > > 3. Some of the syntaxes works for sequence which doesn't make sense to
    > > me, as listed below, I think there are more
    > >
    > > postgres[154731]=# CREATE PUBLICATION insert_only FOR ALL SEQUENCES
    > > WITH (publish = 'insert');
    > > CREATE PUBLICATION
    > >
    > > postgres[154731]=# CREATE PUBLICATION pub FOR ALL SEQUENCES WITH (
    > > PUBLISH_VIA_PARTITION_ROOT );
    > > CREATE PUBLICATION
    >
    > There is a documentation for this at sql-createpublication.html:
    > WITH ( publication_parameter [= value] [, ... ] )
    >     This clause specifies optional parameters for a publication when
    > publishing tables. This clause is not applicable for sequences.
    >
    > I felt it was enough, should we do anything more here?
    >
    
    It would be better if we can give ERROR for options that are not
    specific to sequences.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  278. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-07-21T09:42:50Z

    On Mon, Jul 21, 2025 at 2:23 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 21 Jul 2025 at 10:36, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > I was just trying a different test, so I realized that ALTER
    > > PUBLICATION ADD SEQUENCE is not supported, any reason for the same?
    > >
    > > postgres[154731]=# ALTER PUBLICATION pub ADD sequence s1;
    > > ERROR:  42601: invalid publication object list
    > > LINE 1: ALTER PUBLICATION pub ADD sequence s1;
    > > DETAIL:  One of TABLE or TABLES IN SCHEMA must be specified before a
    > > standalone table or schema name.
    > > LOCATION:  preprocess_pubobj_list, gram.y:19685
    >
    > I have intentionally left this out for now. Once the current patch is
    > committed, we can extend it.
    
    Okay
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  279. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-07-21T09:54:39Z

    On Mon, Jul 21, 2025 at 2:36 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 21 Jul 2025 at 11:15, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Mon, Jul 21, 2025 at 10:36 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > >
    > > > I was just trying a different test, so I realized that ALTER
    > > > PUBLICATION ADD SEQUENCE is not supported, any reason for the same?
    > > >
    > > > postgres[154731]=# ALTER PUBLICATION pub ADD sequence s1;
    > > > ERROR:  42601: invalid publication object list
    > > > LINE 1: ALTER PUBLICATION pub ADD sequence s1;
    > > > DETAIL:  One of TABLE or TABLES IN SCHEMA must be specified before a
    > > > standalone table or schema name.
    > > > LOCATION:  preprocess_pubobj_list, gram.y:19685
    > > >
    > > Also I noticed that
    > > 1. We don't allow creating publication with individual sequences (e.g.
    > > CREATE PUBLICATION pub FOR SEQUENCE s1;).  Is it because the main
    > > purpose of this sync is major version upgrade and we do not have
    > > scenarios for replicating a few sequences or there are some technical
    > > difficulties in achieving that or both.
    >
    > There are no technical difficulties here. The main goal was to support
    > all sequences necessary for the upgrade scenario. Once that is
    > complete, the implementation can be extended based on additional use
    > cases.
    >
    > > 2. This syntax works (CREATE PUBLICATION pub FOR ALL TABLES,
    > > SEQUENCES;) but tab completion doesn't suggest this
    >
    > Nisha had analysed this and shared this  earlier at [1]:
    > Tab-completion is not supported after a comma (,) in any other cases.
    > For example, the following commands are valid, but tab-completion does
    > not work after the comma:
    > CREATE PUBLICATION pub7 FOR TABLE t1, TABLES IN SCHEMA public;
    > CREATE PUBLICATION pub7 FOR TABLES IN SCHEMA public, TABLES IN SCHEMA schema2;
    >
    > > 3. Some of the syntaxes works for sequence which doesn't make sense to
    > > me, as listed below, I think there are more
    > >
    > > postgres[154731]=# CREATE PUBLICATION insert_only FOR ALL SEQUENCES
    > > WITH (publish = 'insert');
    > > CREATE PUBLICATION
    > >
    > > postgres[154731]=# CREATE PUBLICATION pub FOR ALL SEQUENCES WITH (
    > > PUBLISH_VIA_PARTITION_ROOT );
    > > CREATE PUBLICATION
    >
    > There is a documentation for this at sql-createpublication.html:
    > WITH ( publication_parameter [= value] [, ... ] )
    >     This clause specifies optional parameters for a publication when
    > publishing tables. This clause is not applicable for sequences.
    >
    > I felt it was enough, should we do anything more here?
    >
    > [1] - https://www.postgresql.org/message-id/CABdArM5axwoTorZnJww5rE79SNzvnnXCfWkv7XJex1Rkz%3DJDog%40mail.gmail.com
    
    I meant the PUBLISH_VIA_PARTITION_ROOT and other options inside the
    WITH() that are not applicable for SEQUENCES, so shall we throw an
    error if we are only publishing sequences and using these options?
    
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  280. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-21T10:46:00Z

    On Mon, Jul 21, 2025 at 2:55 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Mon, Jul 21, 2025 at 2:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Mon, 21 Jul 2025 at 11:15, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > >
    > >
    > > > 3. Some of the syntaxes works for sequence which doesn't make sense to
    > > > me, as listed below, I think there are more
    > > >
    > > > postgres[154731]=# CREATE PUBLICATION insert_only FOR ALL SEQUENCES
    > > > WITH (publish = 'insert');
    > > > CREATE PUBLICATION
    > > >
    > > > postgres[154731]=# CREATE PUBLICATION pub FOR ALL SEQUENCES WITH (
    > > > PUBLISH_VIA_PARTITION_ROOT );
    > > > CREATE PUBLICATION
    > >
    > > There is a documentation for this at sql-createpublication.html:
    > > WITH ( publication_parameter [= value] [, ... ] )
    > >     This clause specifies optional parameters for a publication when
    > > publishing tables. This clause is not applicable for sequences.
    > >
    > > I felt it was enough, should we do anything more here?
    > >
    >
    > It would be better if we can give ERROR for options that are not
    > specific to sequences.
    >
    
    Alter-PUB also should give an error then. Currently it works
    
    postgres=# alter publication pub1 set (publish='insert,update');
    ALTER PUBLICATION
    
    pub1 here is an all-sequence publication.
    
    Also, we need to decide behaviour for a publication with 'all tables,
    all sequences' having such WITH options for both CREATE and ALTER-PUB.
    The options are valid for tables but not for sequences. In such a
    case, giving an error might not be correct. For this particular case,
    we can give a  NOTICE saying options not applicable to sequences.
    Thoughts?
    
    thanks
    Shveta
    
    
    
    
  281. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-23T06:52:52Z

    On Mon, 21 Jul 2025 at 15:24, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Mon, Jul 21, 2025 at 2:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Mon, 21 Jul 2025 at 11:15, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > >
    > > > On Mon, Jul 21, 2025 at 10:36 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > > >
    > > > > I was just trying a different test, so I realized that ALTER
    > > > > PUBLICATION ADD SEQUENCE is not supported, any reason for the same?
    > > > >
    > > > > postgres[154731]=# ALTER PUBLICATION pub ADD sequence s1;
    > > > > ERROR:  42601: invalid publication object list
    > > > > LINE 1: ALTER PUBLICATION pub ADD sequence s1;
    > > > > DETAIL:  One of TABLE or TABLES IN SCHEMA must be specified before a
    > > > > standalone table or schema name.
    > > > > LOCATION:  preprocess_pubobj_list, gram.y:19685
    > > > >
    > > > Also I noticed that
    > > > 1. We don't allow creating publication with individual sequences (e.g.
    > > > CREATE PUBLICATION pub FOR SEQUENCE s1;).  Is it because the main
    > > > purpose of this sync is major version upgrade and we do not have
    > > > scenarios for replicating a few sequences or there are some technical
    > > > difficulties in achieving that or both.
    > >
    > > There are no technical difficulties here. The main goal was to support
    > > all sequences necessary for the upgrade scenario. Once that is
    > > complete, the implementation can be extended based on additional use
    > > cases.
    > >
    > > > 2. This syntax works (CREATE PUBLICATION pub FOR ALL TABLES,
    > > > SEQUENCES;) but tab completion doesn't suggest this
    > >
    > > Nisha had analysed this and shared this  earlier at [1]:
    > > Tab-completion is not supported after a comma (,) in any other cases.
    > > For example, the following commands are valid, but tab-completion does
    > > not work after the comma:
    > > CREATE PUBLICATION pub7 FOR TABLE t1, TABLES IN SCHEMA public;
    > > CREATE PUBLICATION pub7 FOR TABLES IN SCHEMA public, TABLES IN SCHEMA schema2;
    > >
    > > > 3. Some of the syntaxes works for sequence which doesn't make sense to
    > > > me, as listed below, I think there are more
    > > >
    > > > postgres[154731]=# CREATE PUBLICATION insert_only FOR ALL SEQUENCES
    > > > WITH (publish = 'insert');
    > > > CREATE PUBLICATION
    > > >
    > > > postgres[154731]=# CREATE PUBLICATION pub FOR ALL SEQUENCES WITH (
    > > > PUBLISH_VIA_PARTITION_ROOT );
    > > > CREATE PUBLICATION
    > >
    > > There is a documentation for this at sql-createpublication.html:
    > > WITH ( publication_parameter [= value] [, ... ] )
    > >     This clause specifies optional parameters for a publication when
    > > publishing tables. This clause is not applicable for sequences.
    > >
    > > I felt it was enough, should we do anything more here?
    > >
    > > [1] - https://www.postgresql.org/message-id/CABdArM5axwoTorZnJww5rE79SNzvnnXCfWkv7XJex1Rkz%3DJDog%40mail.gmail.com
    >
    > I meant the PUBLISH_VIA_PARTITION_ROOT and other options inside the
    > WITH() that are not applicable for SEQUENCES, so shall we throw an
    > error if we are only publishing sequences and using these options?
    
    This is handled in the v20250723 version patch attached.
    
    Also the comment from [1] is addressed.
    [1] - https://www.postgresql.org/message-id/CAJpy0uB0HmmiqrE5DrvH-jZPgSM7iiObGuTbg5JeOrEPT_5xPw%40mail.gmail.com
    
    Regards,
    Vignesh
    
  282. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-07-24T07:42:31Z

    Dear Vignesh,
    
    Thanks for working the project. Here are my comments only for 0001 and 0002.
    Sorry if my points have already been discussed, this thread is too huge to catchup for me :-(.
    
    01.
    Do we have to document the function and open to users? Previously it was not.
    Another example is pg_get_publication_tables, which is used only by the backend.
    
    02.
    ```
    SELECT last_value, is_called, log_cnt FROM pg_get_sequence_data('test_seq1');
    ```
    
    I came up with the way that the function returns page_lsn, how do you feel?
    
    ```
    SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    ```
    
    03.
    Regarding the tab completion on psql. When I input till "CREATE PUBLICATION pub FOR ALL TABLES"
    and push the tab, the word "WITH" was completed. But I'm afraid it may be too
    much because users can input like "FOR ALL TABLES, ALL SEQUENCES". Should we
    suggest the word ", ALL SEQUENCES" here or we can ignore?
    
    Same point can be said when "FOR ALL SEQUENCES" was input.
    
    04.
    Same as above, "WITH" could be completed when I input till "FOR ALL SEQUENCES".
    However, current patch rejects the WITH clause for ALL SEQUENCE publication.
    How do you feel? I'm wondering we should stop the suggestion.
    
    05.
    is_publishable_class() has a comment atop the function:
    ```
     * Does same checks as check_publication_add_relation() above, but does not
     * need relation to be opened and also does not throw errors.
    ```
    
    But this is not correct becasue check_publication_add_relation() does not allow
    sequences. Can you modify the comment accordingly?
    
    06.
    ```
    	values[Anum_pg_publication_puballtables - 1] = stmt->for_all_tables;
    	values[Anum_pg_publication_puballsequences - 1] = stmt->for_all_sequences;
    ```
    
    They should be passed as Datum like others.
    
    07.
    ```
    +       /*
    +        * indicates that this is special publication which should encompass all
    +        * sequences in the database (except for the unlogged and temp ones)
    +        */
    +       bool            puballsequences;
    ```
    
    Let me my thought here. I initially wondered whether we should synchronize
    unlogged sequences, because it is actually possible. However, I found the article[1]
    that primal use-case of the unlogged sequence is to associate with the unlogged table.
    Based on the point, I agree not to include such sequences - they might be a leaked
    sequence.
    
    08.
    ```
    @@ -1902,6 +1952,13 @@ PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
                                            errcode(ERRCODE_SYNTAX_ERROR),
                                            errmsg("column list must not be specified in ALTER PUBLICATION ... DROP"));
     
    +               if (RelationGetForm(rel)->relkind == RELKIND_SEQUENCE)
    +                       ereport(ERROR,
    +                                       errcode(ERRCODE_UNDEFINED_OBJECT),
    +                                       errmsg("relation \"%s\" is not part of the publication",
    +                                                  RelationGetRelationName(rel)),
    +                                       errdetail_relkind_not_supported(RelationGetForm(rel)->relkind));
    +
    ```
    
    Hmm, I feel this is not needed because in the first place sequences cannot be
    specified as the target. Other objects like view is not handled here.
    
    09.
    ```
    +       StringInfo      pub_type;
    +
            Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
    ```
    
    I feel this blank is not needed.
    
    10.
    ```
    /*
     * Process all_objects_list to set all_tables/all_sequences.
     * Also, checks if the pub_object_type has been specified more than once.
     */
    static void
    preprocess_pub_all_objtype_list(List *all_objects_list, bool *all_tables,
    								bool *all_sequences, core_yyscan_t yyscanner)
    ```
    
    I'm not a native speaker, but I feel object list is "process"'d here, not
    "preprocess"'d. Can we rename to process_pub_all_objtype_list?
    
    11.
    ```
    +       /* The WITH clause is not applicable to FOR ALL SEQUENCES publications */
    +       if (!pubinfo->puballsequences || pubinfo->puballtables)
    ```
    
    This meant that FOR ALL TABLES/SEQUENCES publication without any options can be
    dumped like:
    
    ```
    CREATE PUBLICATION pub FOR ALL TABLES, ALL SEQUENCES WITH (publish = 'insert, update, delete, truncate')
    ```
    
    However, since the WITH clause is set with ALL SEQUENCE, generated script could
    raise the WARNING, which may be confusing for users:
    
    ```
    $ psql -U postgres -f dump.sql 
    ...
    psql:dump.sql:24: WARNING:  WITH clause parameters do not affect sequence synchronization
    ```
    
    One workaround for it is not to output WITH cause for default setting. Thought?
    
    [1]: https://www.crunchydata.com/blog/postgresql-unlogged-sequences#unlogged-sequences-in-postgres-have-no-performance-gain
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
  283. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-24T15:31:50Z

    On Thu, 24 Jul 2025 at 13:12, Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > Dear Vignesh,
    >
    > Thanks for working the project. Here are my comments only for 0001 and 0002.
    > Sorry if my points have already been discussed, this thread is too huge to catchup for me :-(.
    >
    > 01.
    > Do we have to document the function and open to users? Previously it was not.
    > Another example is pg_get_publication_tables, which is used only by the backend.
    
    Now we are exposing this function to the user, this LSN value will be
    used by the user to find out if the sequence has changed compared to
    the subscriber and decide if it should be synchronized or not.
    
    > 02.
    > ```
    > SELECT last_value, is_called, log_cnt FROM pg_get_sequence_data('test_seq1');
    > ```
    >
    > I came up with the way that the function returns page_lsn, how do you feel?
    >
    > ```
    > SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    > ```
    
    Modified
    
    > 03.
    > Regarding the tab completion on psql. When I input till "CREATE PUBLICATION pub FOR ALL TABLES"
    > and push the tab, the word "WITH" was completed. But I'm afraid it may be too
    > much because users can input like "FOR ALL TABLES, ALL SEQUENCES". Should we
    > suggest the word ", ALL SEQUENCES" here or we can ignore?
    >
    > Same point can be said when "FOR ALL SEQUENCES" was input.
    
    This was discussed earlier at [1]:
    Tab-completion is not supported after a comma (,) in any other cases.
    For example, the following commands are valid, but tab-completion does
    not work after the comma:
    CREATE PUBLICATION pub7 FOR TABLE t1, TABLES IN SCHEMA public;
    CREATE PUBLICATION pub7 FOR TABLES IN SCHEMA public, TABLES IN SCHEMA schema2;
    
    > 04.
    > Same as above, "WITH" could be completed when I input till "FOR ALL SEQUENCES".
    > However, current patch rejects the WITH clause for ALL SEQUENCE publication.
    > How do you feel? I'm wondering we should stop the suggestion.
    
    Modified
    
    > 05.
    > is_publishable_class() has a comment atop the function:
    > ```
    >  * Does same checks as check_publication_add_relation() above, but does not
    >  * need relation to be opened and also does not throw errors.
    > ```
    >
    > But this is not correct becasue check_publication_add_relation() does not allow
    > sequences. Can you modify the comment accordingly?
    
    Modified
    
    > 06.
    > ```
    >         values[Anum_pg_publication_puballtables - 1] = stmt->for_all_tables;
    >         values[Anum_pg_publication_puballsequences - 1] = stmt->for_all_sequences;
    > ```
    >
    > They should be passed as Datum like others.
    
    Modified
    
    > 07.
    > ```
    > +       /*
    > +        * indicates that this is special publication which should encompass all
    > +        * sequences in the database (except for the unlogged and temp ones)
    > +        */
    > +       bool            puballsequences;
    > ```
    >
    > Let me my thought here. I initially wondered whether we should synchronize
    > unlogged sequences, because it is actually possible. However, I found the article[1]
    > that primal use-case of the unlogged sequence is to associate with the unlogged table.
    > Based on the point, I agree not to include such sequences - they might be a leaked
    > sequence.
    
    I agree
    
    > 08.
    > ```
    > @@ -1902,6 +1952,13 @@ PublicationDropTables(Oid pubid, List *rels, bool missing_ok)
    >                                         errcode(ERRCODE_SYNTAX_ERROR),
    >                                         errmsg("column list must not be specified in ALTER PUBLICATION ... DROP"));
    >
    > +               if (RelationGetForm(rel)->relkind == RELKIND_SEQUENCE)
    > +                       ereport(ERROR,
    > +                                       errcode(ERRCODE_UNDEFINED_OBJECT),
    > +                                       errmsg("relation \"%s\" is not part of the publication",
    > +                                                  RelationGetRelationName(rel)),
    > +                                       errdetail_relkind_not_supported(RelationGetForm(rel)->relkind));
    > +
    > ```
    >
    > Hmm, I feel this is not needed because in the first place sequences cannot be
    > specified as the target. Other objects like view is not handled here.
    
    Modified
    
    > 09.
    > ```
    > +       StringInfo      pub_type;
    > +
    >         Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
    > ```
    >
    > I feel this blank is not needed.
    
    Modified
    
    > 10.
    > ```
    > /*
    >  * Process all_objects_list to set all_tables/all_sequences.
    >  * Also, checks if the pub_object_type has been specified more than once.
    >  */
    > static void
    > preprocess_pub_all_objtype_list(List *all_objects_list, bool *all_tables,
    >                                                                 bool *all_sequences, core_yyscan_t yyscanner)
    > ```
    >
    > I'm not a native speaker, but I feel object list is "process"'d here, not
    > "preprocess"'d. Can we rename to process_pub_all_objtype_list?
    
    Since we have an existing function preprocess_pubobj_list which uses
    preprocess, keeping it as preprocess to maintain consistency
    
    > 11.
    > ```
    > +       /* The WITH clause is not applicable to FOR ALL SEQUENCES publications */
    > +       if (!pubinfo->puballsequences || pubinfo->puballtables)
    > ```
    >
    > This meant that FOR ALL TABLES/SEQUENCES publication without any options can be
    > dumped like:
    >
    > ```
    > CREATE PUBLICATION pub FOR ALL TABLES, ALL SEQUENCES WITH (publish = 'insert, update, delete, truncate')
    > ```
    >
    > However, since the WITH clause is set with ALL SEQUENCE, generated script could
    > raise the WARNING, which may be confusing for users:
    >
    > ```
    > $ psql -U postgres -f dump.sql
    > ...
    > psql:dump.sql:24: WARNING:  WITH clause parameters do not affect sequence synchronization
    > ```
    >
    > One workaround for it is not to output WITH cause for default setting. Thought?
    
    I felt this is ok, it will make users aware that for sequence this is
    not applicable.
    
    The attached v20250724 version patch has the changes for the same.
    [1] - https://www.postgresql.org/message-id/CABdArM5axwoTorZnJww5rE79SNzvnnXCfWkv7XJex1Rkz%3DJDog%40mail.gmail.com
    
    Regards,
    Vignesh
    
  284. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-07-28T07:56:18Z

    Dear Vignesh,
    
    Here are remained comments for v20250723 0003-0005. I've not checked the latest version.
    
    01.
    ```
     *	  PostgreSQL logical replication: common synchronization code
    ```
    
    How about: "Common code for synchronizations"? Since this file locates in
    replication/logical, initial part is bit trivial.
    
    02.
    
    How do you feel to separate header file into syncutils.h file? We can put some
    definitions needed for synchronizations.
    
    03.
    ```
    -extern void getSubscriptionTables(Archive *fout);
    +extern void getSubscriptionRelations(Archive *fout);
    ```
    
    Assuming that this function obtains both tables and sequences. I'm now wondering
    we can say "relation" for both the tables and sequences in the context. E.g.,
    getTableData()->makeTableDataInfo() seems to obtain both table and sequence data,
    and dumpSequenceData() dumps sequences. How about keep getSubscriptionTables, or
    getSubscriptionTablesAndSequences?
    
    04.
    ```
    /*
     * dumpSubscriptionTable
     *	  Dump the definition of the given subscription table mapping. This will be
     *    used only in binary-upgrade mode for PG17 or later versions.
     */
    static void
    dumpSubscriptionTable(Archive *fout, const SubRelInfo *subrinfo)
    ```
    
    If you rename getSubscriptionTables, dumpSubscriptionTable should be also renamed.
    
    05.
    ```
    /*
     * Gets list of all relations published by FOR ALL SEQUENCES publication(s).
     */
    List *
    GetAllSequencesPublicationRelations(void)
    ```
    
    It looks very similar with GetAllTablesPublicationRelations(). Can we combine them?
    I feel we can pass the kind of target relation and pubviaroot.
    
    06.
    ```
    --- a/src/backend/catalog/pg_subscription.c
    +++ b/src/backend/catalog/pg_subscription.c
    @@ -27,6 +27,7 @@
     #include "utils/array.h"
     #include "utils/builtins.h"
     #include "utils/fmgroids.h"
    +#include "utils/memutils.h"
    ```
    
    I can build without the header.
    
    07.
    ```
    +       /*
    +        * XXX: If the subscription is for a sequence-only publication, creating a
    +        * replication origin is unnecessary because incremental synchronization
    +        * of sequences is not supported, and sequence data is fully synced during
    +        * a REFRESH, which does not rely on the origin. If the publication is
    +        * later modified to include tables, the origin can be created during the
    +        * ALTER SUBSCRIPTION ... REFRESH command.
    +        */
            ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname));
            replorigin_create(originname);
    ```
    
    The comment is bit misleading because currently we create the replicaton origin
    in the case. Can you clarify the point like:
    ```
    XXX: Now the replication origin is created for all the cases, but it is unnecessary
    when the subcription is for a sequence-only publicaiton....
    ```
    
    08.
    ```
    +                        * XXX: If the subscription is for a sequence-only publication,
    +                        * creating this slot is unnecessary. It can be created later
    +                        * during the ALTER SUBSCRIPTION ... REFRESH PUBLICATION or ALTER
    +                        * SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES command, if the
    +                        * publication is updated to include tables.
    ```
    
    Same as above.
    
    09.
    ```
    + *    Assert copy_data is true.
    + *    Assert refresh_tables is false.
    + *    Assert refresh_sequences is true
    ```
    
    IIUC assertions are rarely described the comment stop function. If you want to
    add, we should say like:
    ```
    In Assert enabled builds, we verify that parameters are passed correctly...
    ```
    
    10.
    ```
    +#ifdef USE_ASSERT_CHECKING
    +       /* Sanity checks for parameter values */
    +       if (resync_all_sequences)
    +               Assert(copy_data && !refresh_tables && refresh_sequences);
    +#endif
    ```
    
    How about below, which does not require ifdef.
    
    ```
    	Assert(!resync_all_sequences ||
    		   (copy_data && !refresh_tables && refresh_sequences));
    
    ```
    
    11.
    ```
    +               bool            issequence;
    +               bool            istable;
    ```
    
    Isn't it enough to use istable?
    
    12.
    ```
    +               /* Relation is either a sequence or a table */
    +               issequence = get_rel_relkind(subrel->srrelid) == RELKIND_SEQUENCE;
    ```
    
    How about adding an Assert() to ensure the relation is either of table or sequence?
    
    13.
    ```
    + * not_ready:
    + * If getting tables and not_ready is false get all tables, otherwise,
    + * only get tables that have not reached READY state.
    + * If getting sequences and not_ready is false get all sequences,
    + * otherwise, only get sequences that have not reached READY state (i.e. are
    + * still in INIT state).
    ```
    Two parts decribe mostly same point. How about:
    If true, this function returns only the relations that are not in a ready state.
    Otherwise returns all the relations of the subscription.
    
    14.
    ```
    +                       char            table_state;
    ```
    
    It should be `relation_state`.
    
    15.
    ```
    +#define SEQ_LOG_CNT_INVALID            0
    ```
    
    Can you add comment how we use it?
    
    16.
    ```
    +
    +       TimestampTz last_seqsync_start_time;
    ```
    
    I can't find the user of this attribute, is it needed?
    
    17.
    ```
    +                               FetchRelationStates(&has_pending_sequences);
    +                               ProcessSyncingTablesForApply(current_lsn);
    +                               if (has_pending_sequences)
    +                                       ProcessSyncingSequencesForApply();
    ```
    
    IIUC we do not always call ProcessSyncingSequencesForApply() because it would acquire
    the LW lock. Can you clariy it as comments?
    
    18.
    ```
    +               case WORKERTYPE_SEQUENCESYNC:
    +                       /* Should never happen. */
    +                       Assert(0);
    ```
    
    Should we call elog(ERROR) instead of Assert(0) like another case?
    
    19.
    ```
    	/* Find the leader apply worker and signal it. */
    	logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    ```
    
    Do we have to signal to the leader even when the sequence worker exits?
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
    
    
    
  285. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-07-28T10:06:55Z

    On Mon, 28 Jul 2025 at 13:26, Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > Dear Vignesh,
    >
    > Here are remained comments for v20250723 0003-0005. I've not checked the latest version.
    >
    > 01.
    > ```
    >  *        PostgreSQL logical replication: common synchronization code
    > ```
    >
    > How about: "Common code for synchronizations"? Since this file locates in
    > replication/logical, initial part is bit trivial.
    
    I felt this is ok as tablesync.c has a similar file header.
    
    > 02.
    >
    > How do you feel to separate header file into syncutils.h file? We can put some
    > definitions needed for synchronizations.
    
    Currently we only have 5 functions here, we can add it if more
    functions get added here.
    
    > 03.
    > ```
    > -extern void getSubscriptionTables(Archive *fout);
    > +extern void getSubscriptionRelations(Archive *fout);
    > ```
    >
    > Assuming that this function obtains both tables and sequences. I'm now wondering
    > we can say "relation" for both the tables and sequences in the context. E.g.,
    > getTableData()->makeTableDataInfo() seems to obtain both table and sequence data,
    > and dumpSequenceData() dumps sequences. How about keep getSubscriptionTables, or
    > getSubscriptionTablesAndSequences?
    
    Retained it to getSubscriptionTables as earlier. As in case of pg_dump
    code it is used like that, that is function having table name not only
    handle table but other relation object too.
    
    > 04.
    > ```
    > /*
    >  * dumpSubscriptionTable
    >  *        Dump the definition of the given subscription table mapping. This will be
    >  *    used only in binary-upgrade mode for PG17 or later versions.
    >  */
    > static void
    > dumpSubscriptionTable(Archive *fout, const SubRelInfo *subrinfo)
    > ```
    >
    > If you rename getSubscriptionTables, dumpSubscriptionTable should be also renamed.
    
    Since we are not renaming getSubscriptionTables, nothing to do here
    
    > 05.
    > ```
    > /*
    >  * Gets list of all relations published by FOR ALL SEQUENCES publication(s).
    >  */
    > List *
    > GetAllSequencesPublicationRelations(void)
    > ```
    >
    > It looks very similar with GetAllTablesPublicationRelations(). Can we combine them?
    > I feel we can pass the kind of target relation and pubviaroot.
    
    Modified
    
    > 06.
    > ```
    > --- a/src/backend/catalog/pg_subscription.c
    > +++ b/src/backend/catalog/pg_subscription.c
    > @@ -27,6 +27,7 @@
    >  #include "utils/array.h"
    >  #include "utils/builtins.h"
    >  #include "utils/fmgroids.h"
    > +#include "utils/memutils.h"
    > ```
    >
    > I can build without the header.
    
    Removed this
    
    > 07.
    > ```
    > +       /*
    > +        * XXX: If the subscription is for a sequence-only publication, creating a
    > +        * replication origin is unnecessary because incremental synchronization
    > +        * of sequences is not supported, and sequence data is fully synced during
    > +        * a REFRESH, which does not rely on the origin. If the publication is
    > +        * later modified to include tables, the origin can be created during the
    > +        * ALTER SUBSCRIPTION ... REFRESH command.
    > +        */
    >         ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname));
    >         replorigin_create(originname);
    > ```
    >
    > The comment is bit misleading because currently we create the replicaton origin
    > in the case. Can you clarify the point like:
    > ```
    > XXX: Now the replication origin is created for all the cases, but it is unnecessary
    > when the subcription is for a sequence-only publicaiton....
    > ```
    
    Modified
    
    > 08.
    > ```
    > +                        * XXX: If the subscription is for a sequence-only publication,
    > +                        * creating this slot is unnecessary. It can be created later
    > +                        * during the ALTER SUBSCRIPTION ... REFRESH PUBLICATION or ALTER
    > +                        * SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES command, if the
    > +                        * publication is updated to include tables.
    > ```
    >
    > Same as above.
    
    Modified
    
    > 09.
    > ```
    > + *    Assert copy_data is true.
    > + *    Assert refresh_tables is false.
    > + *    Assert refresh_sequences is true
    > ```
    >
    > IIUC assertions are rarely described the comment stop function. If you want to
    > add, we should say like:
    > ```
    > In Assert enabled builds, we verify that parameters are passed correctly...
    > ```
    
    Removed these
    
    > 10.
    > ```
    > +#ifdef USE_ASSERT_CHECKING
    > +       /* Sanity checks for parameter values */
    > +       if (resync_all_sequences)
    > +               Assert(copy_data && !refresh_tables && refresh_sequences);
    > +#endif
    > ```
    >
    > How about below, which does not require ifdef.
    >
    > ```
    >         Assert(!resync_all_sequences ||
    >                    (copy_data && !refresh_tables && refresh_sequences));
    >
    > ```
    
    Modified
    
    > 11.
    > ```
    > +               bool            issequence;
    > +               bool            istable;
    > ```
    >
    > Isn't it enough to use istable?
    
    Removed both of them add added relkind variable, which will also help
    next comment
    
    > 12.
    > ```
    > +               /* Relation is either a sequence or a table */
    > +               issequence = get_rel_relkind(subrel->srrelid) == RELKIND_SEQUENCE;
    > ```
    >
    > How about adding an Assert() to ensure the relation is either of table or sequence?
    
    Modified
    
    > 13.
    > ```
    > + * not_ready:
    > + * If getting tables and not_ready is false get all tables, otherwise,
    > + * only get tables that have not reached READY state.
    > + * If getting sequences and not_ready is false get all sequences,
    > + * otherwise, only get sequences that have not reached READY state (i.e. are
    > + * still in INIT state).
    > ```
    > Two parts decribe mostly same point. How about:
    > If true, this function returns only the relations that are not in a ready state.
    > Otherwise returns all the relations of the subscription.
    
    Since we have get_tables and get_sequences, the existing version is more clear
    
    > 14.
    > ```
    > +                       char            table_state;
    > ```
    >
    > It should be `relation_state`.
    
    Modified
    
    > 15.
    > ```
    > +#define SEQ_LOG_CNT_INVALID            0
    > ```
    >
    > Can you add comment how we use it?
    
    We have the following comment in the SetSequence function:
     * log_cnt is currently used only by the sequence syncworker to set the
     * log_cnt for sequences while synchronizing values from the publisher.
    
    Here all others other than sequence syncworker will pass
    SEQ_LOG_CNT_INVALID to set log_cnt to 0.
    
    I felt this is enough.
    
    > 16.
    > ```
    > +
    > +       TimestampTz last_seqsync_start_time;
    > ```
    >
    > I can't find the user of this attribute, is it needed?
    
    This is used in check_and_launch_sync_worker to check in case of
    failures if it has elapsed the wal_retrieve_retry_interval and start
    the sequence sync worker.
    
    > 17.
    > ```
    > +                               FetchRelationStates(&has_pending_sequences);
    > +                               ProcessSyncingTablesForApply(current_lsn);
    > +                               if (has_pending_sequences)
    > +                                       ProcessSyncingSequencesForApply();
    > ```
    >
    > IIUC we do not always call ProcessSyncingSequencesForApply() because it would acquire
    > the LW lock. Can you clariy it as comments?
    
    FetchRelationStates will indicate if there are any sequences to be
    synchronized or not by setting has_pending_sequences. If there are no
    sequences to be synchronized, no point in calling
    ProcessSyncingSequencesForApply. I felt no need to add any comments
    for this. Thoughts?
    
    > 18.
    > ```
    > +               case WORKERTYPE_SEQUENCESYNC:
    > +                       /* Should never happen. */
    > +                       Assert(0);
    > ```
    >
    > Should we call elog(ERROR) instead of Assert(0) like another case?
    
    Modified
    
    > 19.
    > ```
    >         /* Find the leader apply worker and signal it. */
    >         logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    > ```
    >
    > Do we have to signal to the leader even when the sequence worker exits?
    
    Consider the case when the last run apply worker could not allocate an
    tablesync worker because there was no worker that time. Now after the
    sequence sync worker signals apply worker, apply worker can check and
    see if it can be alloted for it, also it can check for any new
    sequences that need to be synced because of refresh publication.
    
    Thanks for the comments, the attached v20250728 version patch has the
    changes for the same.
    
    Regards,
    Vignesh
    
  286. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-30T05:46:14Z

    On Mon, Jul 28, 2025 at 3:37 PM vignesh C <vignesh21@gmail.com> wrote:
    
    > Thanks for the comments, the attached v20250728 version patch has the
    > changes for the same.
    >
    Thanks for the patches, please find a few comments:
    
    1)
    WARNING:  WITH clause parameters do not affect sequence synchronization
    
    a)
    How about:
    WITH clause parameters are not applicable to sequence synchronization
    or
    WITH clause parameters are not applicable to sequence synchronization
    and will be ignored.
    
    b)
    Should it be NOTICE OR WARNING? I feel NOTICE Is more appropriate as
    it is more of an information than a warning since it has no negative
    consequences.
    
    2)
     AlterSubscription_refresh(Subscription *sub, bool copy_data,
    -   List *validate_publications)
    +   List *validate_publications, bool refresh_tables,
    +   bool refresh_sequences, bool resync_all_sequences)
     {
    
    Do we need 3 new arguments? If we notice, 'refresh_sequences' is
    always true in all cases. I feel only the last one should suffice.
    IIUC, this is the state:
    
    When resync_all_sequences is true:
    it indicates it is 'REFRESH PUBLICATION SEQUENCES', that means we have
    to refresh new sequences and resync all sequences.
    
    When resync_all_sequences is false:
    That means it is 'REFRESH PUBLICATION', we have to refresh new tables
    and new sequences alone.
    
    So if the caller pass only 'resync_all_sequences', we should be able
    to drive the rest of the values internally.
    
    3)
     ALTER SUBSCRIPTION regress_testsub REFRESH PUBLICATION;
    -ERROR:  ALTER SUBSCRIPTION ... REFRESH cannot run inside a transaction block
    +ERROR:  ALTER SUBSCRIPTION ... REFRESH PUBLICATION cannot run inside
    a transaction block
    
    In the same script, we can test REFRESH PUBLICATION SEQUENCES also in
    trancsation block.
    
    4)
    Commit message of patch004 says:
    
    This patch introduce a new command to synchronize the sequences of
    a subscription:
    ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES
    
    a)
    introduce --> introduces
    
    b)
    We should also add:
    
    This patch also changes the scope of
    ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    This command now also considers sequences (newly added or dropped ones).
    
    5)
    + * Reset the last_start_time of the sequencesync worker in the subscription's
    + * apply worker.
    
    last_start_time-->last_seqsync_start_time
    
    6)
    alter_subscription.sgml has this:
            <term><literal>refresh</literal> (<type>boolean</type>)</term>
            <listitem>
             <para>
              When false, the command will not try to refresh table information.
              <literal>REFRESH PUBLICATION</literal> should then be
    executed separately.
              The default is <literal>true</literal>.
             </para>
            </listitem>
           </varlistentry>
    
    Shouldn't we mention sequence too here:
    When false, the command will not try to refresh table and sequence information.
    
    thanks
    Shveta
    
    
    
    
  287. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-07-30T08:29:00Z

    On Wed, Jul 30, 2025 at 11:16 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Mon, Jul 28, 2025 at 3:37 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > > Thanks for the comments, the attached v20250728 version patch has the
    > > changes for the same.
    > >
    > Thanks for the patches, please find a few comments:
    >
    > 1)
    > WARNING:  WITH clause parameters do not affect sequence synchronization
    >
    > a)
    > How about:
    > WITH clause parameters are not applicable to sequence synchronization
    > or
    > WITH clause parameters are not applicable to sequence synchronization
    > and will be ignored.
    >
    > b)
    > Should it be NOTICE OR WARNING? I feel NOTICE Is more appropriate as
    > it is more of an information than a warning since it has no negative
    > consequences.
    >
    > 2)
    >  AlterSubscription_refresh(Subscription *sub, bool copy_data,
    > -   List *validate_publications)
    > +   List *validate_publications, bool refresh_tables,
    > +   bool refresh_sequences, bool resync_all_sequences)
    >  {
    >
    > Do we need 3 new arguments? If we notice, 'refresh_sequences' is
    > always true in all cases. I feel only the last one should suffice.
    > IIUC, this is the state:
    >
    > When resync_all_sequences is true:
    > it indicates it is 'REFRESH PUBLICATION SEQUENCES', that means we have
    > to refresh new sequences and resync all sequences.
    >
    > When resync_all_sequences is false:
    > That means it is 'REFRESH PUBLICATION', we have to refresh new tables
    > and new sequences alone.
    >
    > So if the caller pass only 'resync_all_sequences', we should be able
    > to drive the rest of the values internally.
    >
    > 3)
    >  ALTER SUBSCRIPTION regress_testsub REFRESH PUBLICATION;
    > -ERROR:  ALTER SUBSCRIPTION ... REFRESH cannot run inside a transaction block
    > +ERROR:  ALTER SUBSCRIPTION ... REFRESH PUBLICATION cannot run inside
    > a transaction block
    >
    > In the same script, we can test REFRESH PUBLICATION SEQUENCES also in
    > trancsation block.
    >
    > 4)
    > Commit message of patch004 says:
    >
    > This patch introduce a new command to synchronize the sequences of
    > a subscription:
    > ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES
    >
    > a)
    > introduce --> introduces
    >
    > b)
    > We should also add:
    >
    > This patch also changes the scope of
    > ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > This command now also considers sequences (newly added or dropped ones).
    >
    > 5)
    > + * Reset the last_start_time of the sequencesync worker in the subscription's
    > + * apply worker.
    >
    > last_start_time-->last_seqsync_start_time
    >
    > 6)
    > alter_subscription.sgml has this:
    >         <term><literal>refresh</literal> (<type>boolean</type>)</term>
    >         <listitem>
    >          <para>
    >           When false, the command will not try to refresh table information.
    >           <literal>REFRESH PUBLICATION</literal> should then be
    > executed separately.
    >           The default is <literal>true</literal>.
    >          </para>
    >         </listitem>
    >        </varlistentry>
    >
    > Shouldn't we mention sequence too here:
    > When false, the command will not try to refresh table and sequence information.
    >
    
    7)
    I am trying to understand the flow of check_and_launch_sync_worker().
    We acquire the lock(LogicalRepWorkerLock) in the caller and release it
    here. This does not look appropriate. I guess, both
    logicalrep_worker_find() and logicalrep_sync_worker_count() need lock
    to be held, that is why we have done this.  I see that
    logicalrep_worker_launch() (invoked by check_and_launch_sync_worker())
    also does logicalrep_sync_worker_count() and also tries
    garbage-collection once. Shouldn't that suffice? Or is there any
    reason to call logicalrep_sync_worker_count() in
    check_and_launch_sync_worker() additionally? If
    logicalrep_sync_worker_count() is not needed to be called from
    check_and_launch_sync_worker(), the LOCK problem is sorted.
    
    thanks
    Shveta
    
    
    
    
  288. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-08-01T04:33:03Z

    On Wed, 30 Jul 2025 at 11:16, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Mon, Jul 28, 2025 at 3:37 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > > Thanks for the comments, the attached v20250728 version patch has the
    > > changes for the same.
    > >
    > Thanks for the patches, please find a few comments:
    >
    > 1)
    > WARNING:  WITH clause parameters do not affect sequence synchronization
    >
    > a)
    > How about:
    > WITH clause parameters are not applicable to sequence synchronization
    > or
    > WITH clause parameters are not applicable to sequence synchronization
    > and will be ignored.
    
    Modified
    
    > b)
    > Should it be NOTICE OR WARNING? I feel NOTICE Is more appropriate as
    > it is more of an information than a warning since it has no negative
    > consequences.
    
    Modified
    
    > 2)
    >  AlterSubscription_refresh(Subscription *sub, bool copy_data,
    > -   List *validate_publications)
    > +   List *validate_publications, bool refresh_tables,
    > +   bool refresh_sequences, bool resync_all_sequences)
    >  {
    >
    > Do we need 3 new arguments? If we notice, 'refresh_sequences' is
    > always true in all cases. I feel only the last one should suffice.
    > IIUC, this is the state:
    >
    > When resync_all_sequences is true:
    > it indicates it is 'REFRESH PUBLICATION SEQUENCES', that means we have
    > to refresh new sequences and resync all sequences.
    >
    > When resync_all_sequences is false:
    > That means it is 'REFRESH PUBLICATION', we have to refresh new tables
    > and new sequences alone.
    >
    > So if the caller pass only 'resync_all_sequences', we should be able
    > to drive the rest of the values internally.
    
    Modified
    
    > 3)
    >  ALTER SUBSCRIPTION regress_testsub REFRESH PUBLICATION;
    > -ERROR:  ALTER SUBSCRIPTION ... REFRESH cannot run inside a transaction block
    > +ERROR:  ALTER SUBSCRIPTION ... REFRESH PUBLICATION cannot run inside
    > a transaction block
    >
    > In the same script, we can test REFRESH PUBLICATION SEQUENCES also in
    > trancsation block.
    
    Added it
    
    > 4)
    > Commit message of patch004 says:
    >
    > This patch introduce a new command to synchronize the sequences of
    > a subscription:
    > ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES
    >
    > a)
    > introduce --> introduces
    >
    > b)
    > We should also add:
    >
    > This patch also changes the scope of
    > ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > This command now also considers sequences (newly added or dropped ones).
    
    Modified the commit message now to add this information
    
    > 5)
    > + * Reset the last_start_time of the sequencesync worker in the subscription's
    > + * apply worker.
    >
    > last_start_time-->last_seqsync_start_time
    
    Modified
    
    > 6)
    > alter_subscription.sgml has this:
    >         <term><literal>refresh</literal> (<type>boolean</type>)</term>
    >         <listitem>
    >          <para>
    >           When false, the command will not try to refresh table information.
    >           <literal>REFRESH PUBLICATION</literal> should then be
    > executed separately.
    >           The default is <literal>true</literal>.
    >          </para>
    >         </listitem>
    >        </varlistentry>
    >
    > Shouldn't we mention sequence too here:
    > When false, the command will not try to refresh table and sequence information.
    
    Modified
    
    Also, the comment from [1] has been addressed — the lock is now
    released from the caller function itself. Previously, the lock was
    required to fetch the number of sync workers running, but this has
    been refactored to retrieve the count within the caller function
    instead.
    
    Thanks for the comments, the attached patch has the changes for the same.
    [1] - https://www.postgresql.org/message-id/CAJpy0uBCOmoyc44J46PpHbip0Sovqm99cL%3DAJoAErXG0EN2Duw%40mail.gmail.com
    
    Regards,
    Vignesh
    
  289. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-08-01T10:47:53Z

    Dear Vignesh,
    
    I played with your patch and found something.
    
    01.
    In LogicalRepSyncSequences() and GetSubscriptionRelations(), there is a possibility
    that the sequence on the subscriber could be dropped before opens that.
    This can cause `could not open relation with OID %u` error, which is not user-friendly.
    Can we avoid that? Even if it is difficult we should add ereport().
    
    02.
    ```
    		/*
    		 * Check that our sequencesync worker has permission to insert into
    		 * the target sequence.
    		 */
    		aclresult = pg_class_aclcheck(RelationGetRelid(sequence_rel), GetUserId(),
    									  ACL_INSERT);
    		if (aclresult != ACLCHECK_OK)
    			aclcheck_error(aclresult,
    						   get_relkind_objtype(sequence_rel->rd_rel->relkind),
    						   seqname);
    ```
    
    Hmm, but upcoming SetSequence() needs UPDATE privilege. I feel it should be checked.
    
    03.
    Similar with 1, sequences can be dropped just before entering copy_sequences().
    This can cause `cache lookup failed for sequence` error, which cannot be translated.
    Can we avoid that or change the error-function to erport()?
    
    04.
    ```
    				if (message_level_is_interesting(DEBUG1))
    					ereport(DEBUG1,
    							errmsg_internal("logical replication synchronization for subscription \"%s\", sequence \"%s.%s\" has finished",
    											MySubscription->name,
    											seqinfo->nspname,
    											seqinfo->seqname));
    ```
    
    I feel no need to add if-statement because we do not touch additional data here.
    
    05.
    ```
    	list_free_deep(sequences_to_copy);
    ```
    
    IIUC, this function free's each elements and list itself, but they do no-op for
    attributes of elements. Can we pfree() for seqname and nspname?
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
  290. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-08-06T08:57:57Z

    On Fri, 1 Aug 2025 at 16:18, Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > Dear Vignesh,
    >
    > I played with your patch and found something.
    >
    > 01.
    > In LogicalRepSyncSequences() and GetSubscriptionRelations(), there is a possibility
    > that the sequence on the subscriber could be dropped before opens that.
    > This can cause `could not open relation with OID %u` error, which is not user-friendly.
    > Can we avoid that? Even if it is difficult we should add ereport().
    
    Addressed this by taking RowExclusiveLock on the sequence while
    preparing the list
    
    > 02.
    > ```
    >                 /*
    >                  * Check that our sequencesync worker has permission to insert into
    >                  * the target sequence.
    >                  */
    >                 aclresult = pg_class_aclcheck(RelationGetRelid(sequence_rel), GetUserId(),
    >                                                                           ACL_INSERT);
    >                 if (aclresult != ACLCHECK_OK)
    >                         aclcheck_error(aclresult,
    >                                                    get_relkind_objtype(sequence_rel->rd_rel->relkind),
    >                                                    seqname);
    > ```
    >
    > Hmm, but upcoming SetSequence() needs UPDATE privilege. I feel it should be checked.
    
    Modified
    
    > 03.
    > Similar with 1, sequences can be dropped just before entering copy_sequences().
    > This can cause `cache lookup failed for sequence` error, which cannot be translated.
    > Can we avoid that or change the error-function to erport()?
    
    Changed it to log this sequence concurrently dropped
    
    > 04.
    > ```
    >                                 if (message_level_is_interesting(DEBUG1))
    >                                         ereport(DEBUG1,
    >                                                         errmsg_internal("logical replication synchronization for subscription \"%s\", sequence \"%s.%s\" has finished",
    >                                                                                         MySubscription->name,
    >                                                                                         seqinfo->nspname,
    >                                                                                         seqinfo->seqname));
    > ```
    >
    > I feel no need to add if-statement because we do not touch additional data here.
    
    Modified
    
    > 05.
    > ```
    >         list_free_deep(sequences_to_copy);
    > ```
    >
    > IIUC, this function free's each elements and list itself, but they do no-op for
    > attributes of elements. Can we pfree() for seqname and nspname?
    
    Modified
    
    The attached v20250806 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  291. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-08-06T10:59:39Z

    On Wed, Aug 6, 2025 at 2:28 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > The attached v20250806 version patch has the changes for the same.
    >
    
    Thank You for the patches. Please find a few comments:
    
    1)
     * If 'resync_all_sequences' is false:
     *     Add or remove tables and sequences that have been added to or removed
     *         from the publication since the last subscription creation or refresh.
     * If 'resync_all_sequences' is true:
     *     Perform the above operation only for sequences.
    
    Shall we update:
     Perform the above operation only for sequences and resync all the
    sequences including existing ones.
    
    2)
    XLogRecPtr      srsublsn BKI_FORCE_NULL;        /* remote LSN of the
    state change
    
    Shall we rename it to srremotelsn or srremlsn? srsublsn gives a
    feeling that it is local lsn and should be in sync with the one
    displayed by pg_get_sequence_data() locally but that is not the case.
    
    3)
    create sequence myseq1 start 1 increment 100;
    postgres=# select last_value, is_called, log_cnt, page_lsn  from
    pg_get_sequence_data('myseq1');
     last_value | is_called | log_cnt |  page_lsn
    ------------+-----------+---------+------------
              1 | f         |       0 | 0/017BEF10
    
    postgres=# select sequencename, last_value from pg_sequences;
     sequencename | last_value
    --------------+------------
     myseq1       |
    
    For a fresh sequence created, last_value shown by pg_get_sequence_data
    seems wrong. On doging nextval for the first time, last_value shown by
    pg_get_sequence_data does not change as the original value was wrong
    itself to start with.
    
    4)
    +        Returns information about the sequence. <literal>last_value</literal>
    +        is the current value of the sequence, <literal>is_called</literal>
    
    It looks odd to say that 'last_value is the current value of the
    sequence'. Why don't we name it curr_val? If this is an existing
    function and thus we do not want to change the name, then we can say
    something on the line that 'last sequence value set in sequence by
    nextval or setval' or something
    similar to what pg_sequences says for last_value.
    
    5)
    +        and <literal>page_lsn</literal> is the page LSN of the sequence
    +        relation.
    
    Is the page_lsn the page lsn of sequence relation or lsn of the last
    WAL record written (or in simpler terms that particular record's
    page_lsn)? If it is relation page-lsn, it should not change.
    
    6)
    I have noticed that when I do nextval, logcnt reduces and page_lsn is
    not changed until it crosses the threshold. This is in context of
    output returned by pg_get_sequence_data. But on doing setval, page_lsn
    changes everytime and logcnt is reset to 0. Is this expected behaviour
    or the issue in output of pg_get_sequence_data()? I did not get this
    information from setval's doc. Can you please review and confirm?
    
    postgres=# SELECT nextval('myseq2');
     nextval
    ---------
         155
    postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    pg_get_sequence_data('myseq2');
     last_value | is_called | log_cnt |  page_lsn
    ------------+-----------+---------+------------
            155 | t         |      28 | 0/017C4498
    
    postgres=# SELECT nextval('myseq2');
     nextval
    ---------
         175
    
    postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    pg_get_sequence_data('myseq2');
     last_value | is_called | log_cnt |  page_lsn
    ------------+-----------+---------+------------
            175 | t         |      27 | 0/017C4498
    
    postgres=# SELECT setval('myseq2', 55, true);
     setval
    --------
         55
    
    postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    pg_get_sequence_data('myseq2');
     last_value | is_called | log_cnt |  page_lsn
    ------------+-----------+---------+------------
             55 | t         |       0 | 0/017C4568
    
    thanks
    Shveta
    
    
    
    
  292. Re: Logical Replication of sequences

    Nisha Moond <nisha.moond412@gmail.com> — 2025-08-06T12:43:58Z

    On Wed, Aug 6, 2025 at 2:28 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > The attached v20250806 version patch has the changes for the same.
    >
    Thank You for the patches.
    
    patch-0005: sequencesync.c
    + aclresult = pg_class_aclcheck(RelationGetRelid(sequence_rel), GetUserId(),
    +   ACL_UPDATE);
    + if (aclresult != ACLCHECK_OK)
    + aclcheck_error(aclresult,
    +    get_relkind_objtype(sequence_rel->rd_rel->relkind),
    +    seqname);
    
    I see that the run_as_owner check has been removed from
    LogicalRepSyncSequences() and added to copy_sequences() for the
    SetSequence() call.
    
    However, IIUC, the same check is also needed in
    LogicalRepSyncSequences(). Currently, the sequencesync worker can fail
    in the above permission check since user switching doesn’t happen when
    run_as_owner is false.
    
    ```
    ERROR:  permission denied for sequence n1
    ```
    Should we add the run_as_owner handling here as well to avoid this?
    
    --
    Thanks,
    Nisha
    
    
    
    
  293. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-08-07T03:50:53Z

    On Wed, Aug 6, 2025 at 4:29 PM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Wed, Aug 6, 2025 at 2:28 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached v20250806 version patch has the changes for the same.
    > >
    >
    > Thank You for the patches. Please find a few comments:
    >
    > 1)
    >  * If 'resync_all_sequences' is false:
    >  *     Add or remove tables and sequences that have been added to or removed
    >  *         from the publication since the last subscription creation or refresh.
    >  * If 'resync_all_sequences' is true:
    >  *     Perform the above operation only for sequences.
    >
    > Shall we update:
    >  Perform the above operation only for sequences and resync all the
    > sequences including existing ones.
    >
    > 2)
    > XLogRecPtr      srsublsn BKI_FORCE_NULL;        /* remote LSN of the
    > state change
    >
    > Shall we rename it to srremotelsn or srremlsn? srsublsn gives a
    > feeling that it is local lsn and should be in sync with the one
    > displayed by pg_get_sequence_data() locally but that is not the case.
    >
    > 3)
    > create sequence myseq1 start 1 increment 100;
    > postgres=# select last_value, is_called, log_cnt, page_lsn  from
    > pg_get_sequence_data('myseq1');
    >  last_value | is_called | log_cnt |  page_lsn
    > ------------+-----------+---------+------------
    >           1 | f         |       0 | 0/017BEF10
    >
    > postgres=# select sequencename, last_value from pg_sequences;
    >  sequencename | last_value
    > --------------+------------
    >  myseq1       |
    >
    > For a fresh sequence created, last_value shown by pg_get_sequence_data
    > seems wrong. On doging nextval for the first time, last_value shown by
    > pg_get_sequence_data does not change as the original value was wrong
    > itself to start with.
    >
    > 4)
    > +        Returns information about the sequence. <literal>last_value</literal>
    > +        is the current value of the sequence, <literal>is_called</literal>
    >
    > It looks odd to say that 'last_value is the current value of the
    > sequence'. Why don't we name it curr_val? If this is an existing
    > function and thus we do not want to change the name, then we can say
    > something on the line that 'last sequence value set in sequence by
    > nextval or setval' or something
    > similar to what pg_sequences says for last_value.
    >
    > 5)
    > +        and <literal>page_lsn</literal> is the page LSN of the sequence
    > +        relation.
    >
    > Is the page_lsn the page lsn of sequence relation or lsn of the last
    > WAL record written (or in simpler terms that particular record's
    > page_lsn)? If it is relation page-lsn, it should not change.
    >
    > 6)
    > I have noticed that when I do nextval, logcnt reduces and page_lsn is
    > not changed until it crosses the threshold. This is in context of
    > output returned by pg_get_sequence_data. But on doing setval, page_lsn
    > changes everytime and logcnt is reset to 0. Is this expected behaviour
    > or the issue in output of pg_get_sequence_data()? I did not get this
    > information from setval's doc. Can you please review and confirm?
    >
    > postgres=# SELECT nextval('myseq2');
    >  nextval
    > ---------
    >      155
    > postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    > pg_get_sequence_data('myseq2');
    >  last_value | is_called | log_cnt |  page_lsn
    > ------------+-----------+---------+------------
    >         155 | t         |      28 | 0/017C4498
    >
    > postgres=# SELECT nextval('myseq2');
    >  nextval
    > ---------
    >      175
    >
    > postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    > pg_get_sequence_data('myseq2');
    >  last_value | is_called | log_cnt |  page_lsn
    > ------------+-----------+---------+------------
    >         175 | t         |      27 | 0/017C4498
    >
    > postgres=# SELECT setval('myseq2', 55, true);
    >  setval
    > --------
    >      55
    >
    > postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    > pg_get_sequence_data('myseq2');
    >  last_value | is_called | log_cnt |  page_lsn
    > ------------+-----------+---------+------------
    >          55 | t         |       0 | 0/017C4568
    >
    
    
    7)
    For an all-seq publication, we see this:
    
     Owner  | All tables | All sequences | Inserts | Updates | Deletes |
    Truncates | Generated columns | Via root
    --------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
     shveta | f          | t             | t       | t       | t       | t
            | none              | f
    (1 row)
    
    I feel Inserts, Updates, Deletes and Truncates -- all should be marked
    as 'f' instead of default 't'. If we look at the doc of
    pg_publication, it points to DML operations of these pages while
    explaining pubinsert, pubupdate etc. These DML operations have no
    meaning for sequences, thus it makes more sense to make these as 'f'
    for sequences.  Thoughts?
    
    8)
    In pg_publication doc, we shall have a NOTE mentioning that pubinsert,
    pubupdate, pubdelete, pubtruncate are not applicable to sequences and
    thus will always be false for an all-seq publication. For an all
    table, all seq publication; these fields will reflect values for
    tables alone.
    
    9)
    GetAllTablesPublicationRelations
    
    Earlier we had this name because the publication was for 'ALL TABLES',
    but now it could be ALL SEQUNECES too. We shall rename this function.
    Some options are: GetAllPublicationRelations,
    GetPublicationRelationsForAll,
    GetPublicationRelationsForAllTablesSequences
    
    thanks
    Shveta
    
    
    
    
  294. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-08-13T10:56:58Z

    On Wed, 6 Aug 2025 at 16:29, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Wed, Aug 6, 2025 at 2:28 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached v20250806 version patch has the changes for the same.
    > >
    >
    > Thank You for the patches. Please find a few comments:
    >
    > 1)
    >  * If 'resync_all_sequences' is false:
    >  *     Add or remove tables and sequences that have been added to or removed
    >  *         from the publication since the last subscription creation or refresh.
    >  * If 'resync_all_sequences' is true:
    >  *     Perform the above operation only for sequences.
    >
    > Shall we update:
    >  Perform the above operation only for sequences and resync all the
    > sequences including existing ones.
    
    Modified
    
    > 2)
    > XLogRecPtr      srsublsn BKI_FORCE_NULL;        /* remote LSN of the
    > state change
    >
    > Shall we rename it to srremotelsn or srremlsn? srsublsn gives a
    > feeling that it is local lsn and should be in sync with the one
    > displayed by pg_get_sequence_data() locally but that is not the case.
    
    I felt this is an existing column which is also used for tables, the
    same table behavior is used for sequences too. Since this is an
    existing column which has been used from long time, I prefer not to
    change it.
    
    > 3)
    > create sequence myseq1 start 1 increment 100;
    > postgres=# select last_value, is_called, log_cnt, page_lsn  from
    > pg_get_sequence_data('myseq1');
    >  last_value | is_called | log_cnt |  page_lsn
    > ------------+-----------+---------+------------
    >           1 | f         |       0 | 0/017BEF10
    >
    > postgres=# select sequencename, last_value from pg_sequences;
    >  sequencename | last_value
    > --------------+------------
    >  myseq1       |
    >
    > For a fresh sequence created, last_value shown by pg_get_sequence_data
    > seems wrong. On doging nextval for the first time, last_value shown by
    > pg_get_sequence_data does not change as the original value was wrong
    > itself to start with.
    
    This behavior is implemented like that in the base code. I will
    analyze more why it was implemented like that and discuss this in the
    original thread.
    
    > 4)
    > +        Returns information about the sequence. <literal>last_value</literal>
    > +        is the current value of the sequence, <literal>is_called</literal>
    >
    > It looks odd to say that 'last_value is the current value of the
    > sequence'. Why don't we name it curr_val? If this is an existing
    > function and thus we do not want to change the name, then we can say
    > something on the line that 'last sequence value set in sequence by
    > nextval or setval' or something
    > similar to what pg_sequences says for last_value.
    
    Modified
    
    > 5)
    > +        and <literal>page_lsn</literal> is the page LSN of the sequence
    > +        relation.
    >
    > Is the page_lsn the page lsn of sequence relation or lsn of the last
    > WAL record written (or in simpler terms that particular record's
    > page_lsn)? If it is relation page-lsn, it should not change.
    
    Updated documentation
    
    > 6)
    > I have noticed that when I do nextval, logcnt reduces and page_lsn is
    > not changed until it crosses the threshold. This is in context of
    > output returned by pg_get_sequence_data. But on doing setval, page_lsn
    > changes everytime and logcnt is reset to 0. Is this expected behaviour
    > or the issue in output of pg_get_sequence_data()? I did not get this
    > information from setval's doc. Can you please review and confirm?
    >
    > postgres=# SELECT nextval('myseq2');
    >  nextval
    > ---------
    >      155
    > postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    > pg_get_sequence_data('myseq2');
    >  last_value | is_called | log_cnt |  page_lsn
    > ------------+-----------+---------+------------
    >         155 | t         |      28 | 0/017C4498
    >
    > postgres=# SELECT nextval('myseq2');
    >  nextval
    > ---------
    >      175
    >
    > postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    > pg_get_sequence_data('myseq2');
    >  last_value | is_called | log_cnt |  page_lsn
    > ------------+-----------+---------+------------
    >         175 | t         |      27 | 0/017C4498
    >
    > postgres=# SELECT setval('myseq2', 55, true);
    >  setval
    > --------
    >      55
    >
    > postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    > pg_get_sequence_data('myseq2');
    >  last_value | is_called | log_cnt |  page_lsn
    > ------------+-----------+---------+------------
    >          55 | t         |       0 | 0/017C4568
    
    I believe this behavior is expected. In the case of nextval,
    PostgreSQL prefetches 32 values in advance and uses the increment_by
    setting to serve the next value from this cached range. Since these
    values are predictable and already reserved, they don't need to be
    WAL-logged individually.
    However, with setval, the new value being set is arbitrary and cannot
    be assumed to follow the previous sequence. It could be a jump
    forward, backward, or even the same value. Because of this
    unpredictability, the change must be explicitly WAL-logged to ensure
    durability and consistency in case of recovery.
    
    Please find my response for the comments from [1]:
    >7)
    >For an all-seq publication, we see this:
    >
    > Owner  | All tables | All sequences | Inserts | Updates | Deletes |
    >Truncates | Generated columns | Via root
    >--------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
    > shveta | f          | t             | t       | t       | t       | t
    >        | none              | f
    >(1 row)
    >
    >I feel Inserts, Updates, Deletes and Truncates -- all should be marked
    >as 'f' instead of default 't'. If we look at the doc of
    >pg_publication, it points to DML operations of these pages while
    >explaining pubinsert, pubupdate etc. These DML operations have no
    >meaning for sequences, thus it makes more sense to make these as 'f'
    >for sequences.  Thoughts?
    
    Modified
    
    >8)
    >In pg_publication doc, we shall have a NOTE mentioning that pubinsert,
    >pubupdate, pubdelete, pubtruncate are not applicable to sequences and
    >thus will always be false for an all-seq publication. For an all
    >table, all seq publication; these fields will reflect values for
    >tables alone.
    
    I felt this is not required, it is mentioned in the docs that it is
    only for tables. ex: If true, INSERT operations are replicated for
    tables in the publication.
    
    >9)
    >GetAllTablesPublicationRelations
    >
    >Earlier we had this name because the publication was for 'ALL TABLES',
    >but now it could be ALL SEQUNECES too. We shall rename this function.
    >Some options are: GetAllPublicationRelations,
    >GetPublicationRelationsForAll,
    >GetPublicationRelationsForAllTablesSequences
    
    Modified it to GetAllPublicationRelations
    
    Please find my response for the comments from [2]:
    >patch-0005: sequencesync.c
    >+ aclresult = pg_class_aclcheck(RelationGetRelid(sequence_rel), GetUserId(),
    >+   ACL_UPDATE);
    >+ if (aclresult != ACLCHECK_OK)
    >+ aclcheck_error(aclresult,
    >+    get_relkind_objtype(sequence_rel->rd_rel->relkind),
    >+    seqname);
    >
    >I see that the run_as_owner check has been removed from
    >LogicalRepSyncSequences() and added to copy_sequences() for the
    >SetSequence() call.
    >
    >However, IIUC, the same check is also needed in
    >LogicalRepSyncSequences(). Currently, the sequencesync worker can fail
    >in the above permission check since user switching doesn’t happen when
    >run_as_owner is false.
    >
    >```
    >ERROR:  permission denied for sequence n1
    >```
    >Should we add the run_as_owner handling here as well to avoid this?
    
    This check here is not required as this check will be done during the
    set sequence. updated it.
    
    The attached v20250813 patch has the changes for the same.
    [1] - https://www.postgresql.org/message-id/CAJpy0uADzXSyx9YYPB-tuCfNWfGi4__CotQ1T3-q7AwBVCZRrg@mail.gmail.com
    [2] - https://www.postgresql.org/message-id/CABdArM7aY%2Bu5Fv9KMHp_iX%3DAEixfDum5e2ixZkWS8YcOt_NO7Q%40mail.gmail.com
    
    Regards,
    Vignesh
    
  295. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-08-15T11:16:30Z

    Dear Vignesh,
    
    Thanks for updating the patch. Here are my small comments:
    
    01.
    Per pgindent report, publicationcmds.c should be fixed.
    
    02.
    ```
    +       ScanKeyInit(&skey[1],
    +                               Anum_pg_subscription_rel_srsubstate,
    +                               BTEqualStrategyNumber, F_CHARNE,
    +                               CharGetDatum(SUBREL_STATE_READY));
    ```
    
    I felt it is more natural to "srsubstate = 'i'", instead of "srsubstate <> 'r'"
    
    03.
    ```
    +               table_close(sequence_rel, NoLock);
    +       }
    +
    +       /* Cleanup */
    +       systable_endscan(scan);
    +       table_close(rel, AccessShareLock);
    +
    +       CommitTransactionCommand();
    ```
    
    To clarify, can we release the sequence at the end of the inner loop?
    
    I found that sequence relation is closed (but not release the lock) then commit
    the transaction once. This approach cannot avoid dropping it by concurrent
    transactions, but maybe you did due to the performance reason. So...I felt we
    may able to release bit earlier.
    
    04.
    ```
    +                       sequence_rel = try_table_open(seqinfo->localrelid, RowExclusiveLock);
    +
    +                       /* Get the local sequence */
    +                       tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    +                       if (!sequence_rel || !HeapTupleIsValid(tup))
    +                       {
    +                               elog(LOG, "skip synchronization of sequence \"%s.%s\" because it has been dropped concurrently",
    +                                        seqinfo->nspname, seqinfo->seqname);
    +
    +                               batch_skipped_count++;
    +                               continue;
    +                       }
    ```
    
    a. Code comment can be atop try_table_open().
    b. Isn't it enough to check HeapTupleIsValid() here?
    
    05.
    ```
    +                       /* Update the sequence only if the parameters are identical */
    +                       if (seqform->seqtypid == seqtypid &&
    +                               seqform->seqmin == seqmin && seqform->seqmax == seqmax &&
    +                               seqform->seqcycle == seqcycle &&
    +                               seqform->seqstart == seqstart &&
    +                               seqform->seqincrement == seqincrement)
    ```
    
    I noticed that seqcache is not compared. Is there a reason?
    
    06.
    ```
    +       foreach_ptr(LogicalRepSequenceInfo, seq_info, sequences_to_copy)
    +       {
    +               pfree(seq_info->seqname);
    +               pfree(seq_info->nspname);
    +               pfree(seq_info);
    +       }
    ```
    
    Per comment atop foreach_delete_current(), we should not directly do pfree()
    the entry. Can you use foreach_delete_current()? I.e.,
    
    07.
    ```
    	foreach_ptr(LogicalRepSequenceInfo, seq_info, sequences_to_copy)
    	{
    		pfree(seq_info->seqname);
    		pfree(seq_info->nspname);
    		
    		sequences_to_copy =
    			foreach_delete_current(sequences_to_copy, seq_info);
    	}
    ```
    
    08.
    ```
    +$node_subscriber->init(allows_streaming => 'logical');
    ```
    
    Actually no need to set to 'logical'.
    
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
  296. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-08-16T08:44:33Z

    Hi,
    
    On Wed, Aug 13, 2025 at 3:57 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 6 Aug 2025 at 16:29, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Wed, Aug 6, 2025 at 2:28 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > The attached v20250806 version patch has the changes for the same.
    > > >
    > >
    > > Thank You for the patches. Please find a few comments:
    > >
    > > 1)
    > >  * If 'resync_all_sequences' is false:
    > >  *     Add or remove tables and sequences that have been added to or removed
    > >  *         from the publication since the last subscription creation or refresh.
    > >  * If 'resync_all_sequences' is true:
    > >  *     Perform the above operation only for sequences.
    > >
    > > Shall we update:
    > >  Perform the above operation only for sequences and resync all the
    > > sequences including existing ones.
    >
    > Modified
    >
    > > 2)
    > > XLogRecPtr      srsublsn BKI_FORCE_NULL;        /* remote LSN of the
    > > state change
    > >
    > > Shall we rename it to srremotelsn or srremlsn? srsublsn gives a
    > > feeling that it is local lsn and should be in sync with the one
    > > displayed by pg_get_sequence_data() locally but that is not the case.
    >
    > I felt this is an existing column which is also used for tables, the
    > same table behavior is used for sequences too. Since this is an
    > existing column which has been used from long time, I prefer not to
    > change it.
    >
    > > 3)
    > > create sequence myseq1 start 1 increment 100;
    > > postgres=# select last_value, is_called, log_cnt, page_lsn  from
    > > pg_get_sequence_data('myseq1');
    > >  last_value | is_called | log_cnt |  page_lsn
    > > ------------+-----------+---------+------------
    > >           1 | f         |       0 | 0/017BEF10
    > >
    > > postgres=# select sequencename, last_value from pg_sequences;
    > >  sequencename | last_value
    > > --------------+------------
    > >  myseq1       |
    > >
    > > For a fresh sequence created, last_value shown by pg_get_sequence_data
    > > seems wrong. On doging nextval for the first time, last_value shown by
    > > pg_get_sequence_data does not change as the original value was wrong
    > > itself to start with.
    >
    > This behavior is implemented like that in the base code. I will
    > analyze more why it was implemented like that and discuss this in the
    > original thread.
    >
    > > 4)
    > > +        Returns information about the sequence. <literal>last_value</literal>
    > > +        is the current value of the sequence, <literal>is_called</literal>
    > >
    > > It looks odd to say that 'last_value is the current value of the
    > > sequence'. Why don't we name it curr_val? If this is an existing
    > > function and thus we do not want to change the name, then we can say
    > > something on the line that 'last sequence value set in sequence by
    > > nextval or setval' or something
    > > similar to what pg_sequences says for last_value.
    >
    > Modified
    >
    > > 5)
    > > +        and <literal>page_lsn</literal> is the page LSN of the sequence
    > > +        relation.
    > >
    > > Is the page_lsn the page lsn of sequence relation or lsn of the last
    > > WAL record written (or in simpler terms that particular record's
    > > page_lsn)? If it is relation page-lsn, it should not change.
    >
    > Updated documentation
    >
    > > 6)
    > > I have noticed that when I do nextval, logcnt reduces and page_lsn is
    > > not changed until it crosses the threshold. This is in context of
    > > output returned by pg_get_sequence_data. But on doing setval, page_lsn
    > > changes everytime and logcnt is reset to 0. Is this expected behaviour
    > > or the issue in output of pg_get_sequence_data()? I did not get this
    > > information from setval's doc. Can you please review and confirm?
    > >
    > > postgres=# SELECT nextval('myseq2');
    > >  nextval
    > > ---------
    > >      155
    > > postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    > > pg_get_sequence_data('myseq2');
    > >  last_value | is_called | log_cnt |  page_lsn
    > > ------------+-----------+---------+------------
    > >         155 | t         |      28 | 0/017C4498
    > >
    > > postgres=# SELECT nextval('myseq2');
    > >  nextval
    > > ---------
    > >      175
    > >
    > > postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    > > pg_get_sequence_data('myseq2');
    > >  last_value | is_called | log_cnt |  page_lsn
    > > ------------+-----------+---------+------------
    > >         175 | t         |      27 | 0/017C4498
    > >
    > > postgres=# SELECT setval('myseq2', 55, true);
    > >  setval
    > > --------
    > >      55
    > >
    > > postgres=#  select last_value, is_called, log_cnt, page_lsn  from
    > > pg_get_sequence_data('myseq2');
    > >  last_value | is_called | log_cnt |  page_lsn
    > > ------------+-----------+---------+------------
    > >          55 | t         |       0 | 0/017C4568
    >
    > I believe this behavior is expected. In the case of nextval,
    > PostgreSQL prefetches 32 values in advance and uses the increment_by
    > setting to serve the next value from this cached range. Since these
    > values are predictable and already reserved, they don't need to be
    > WAL-logged individually.
    > However, with setval, the new value being set is arbitrary and cannot
    > be assumed to follow the previous sequence. It could be a jump
    > forward, backward, or even the same value. Because of this
    > unpredictability, the change must be explicitly WAL-logged to ensure
    > durability and consistency in case of recovery.
    >
    > Please find my response for the comments from [1]:
    > >7)
    > >For an all-seq publication, we see this:
    > >
    > > Owner  | All tables | All sequences | Inserts | Updates | Deletes |
    > >Truncates | Generated columns | Via root
    > >--------+------------+---------------+---------+---------+---------+-----------+-------------------+----------
    > > shveta | f          | t             | t       | t       | t       | t
    > >        | none              | f
    > >(1 row)
    > >
    > >I feel Inserts, Updates, Deletes and Truncates -- all should be marked
    > >as 'f' instead of default 't'. If we look at the doc of
    > >pg_publication, it points to DML operations of these pages while
    > >explaining pubinsert, pubupdate etc. These DML operations have no
    > >meaning for sequences, thus it makes more sense to make these as 'f'
    > >for sequences.  Thoughts?
    >
    > Modified
    >
    > >8)
    > >In pg_publication doc, we shall have a NOTE mentioning that pubinsert,
    > >pubupdate, pubdelete, pubtruncate are not applicable to sequences and
    > >thus will always be false for an all-seq publication. For an all
    > >table, all seq publication; these fields will reflect values for
    > >tables alone.
    >
    > I felt this is not required, it is mentioned in the docs that it is
    > only for tables. ex: If true, INSERT operations are replicated for
    > tables in the publication.
    >
    > >9)
    > >GetAllTablesPublicationRelations
    > >
    > >Earlier we had this name because the publication was for 'ALL TABLES',
    > >but now it could be ALL SEQUNECES too. We shall rename this function.
    > >Some options are: GetAllPublicationRelations,
    > >GetPublicationRelationsForAll,
    > >GetPublicationRelationsForAllTablesSequences
    >
    > Modified it to GetAllPublicationRelations
    >
    > Please find my response for the comments from [2]:
    > >patch-0005: sequencesync.c
    > >+ aclresult = pg_class_aclcheck(RelationGetRelid(sequence_rel), GetUserId(),
    > >+   ACL_UPDATE);
    > >+ if (aclresult != ACLCHECK_OK)
    > >+ aclcheck_error(aclresult,
    > >+    get_relkind_objtype(sequence_rel->rd_rel->relkind),
    > >+    seqname);
    > >
    > >I see that the run_as_owner check has been removed from
    > >LogicalRepSyncSequences() and added to copy_sequences() for the
    > >SetSequence() call.
    > >
    > >However, IIUC, the same check is also needed in
    > >LogicalRepSyncSequences(). Currently, the sequencesync worker can fail
    > >in the above permission check since user switching doesn’t happen when
    > >run_as_owner is false.
    > >
    > >```
    > >ERROR:  permission denied for sequence n1
    > >```
    > >Should we add the run_as_owner handling here as well to avoid this?
    >
    > This check here is not required as this check will be done during the
    > set sequence. updated it.
    >
    
    As I understand it, the logical replication of sequences implemented
    by these patches shares the same user interface as table replication
    (utilizing CREATE PUBLICATION and CREATE SUBSCRIPTION commands for
    configuration). However, the underlying replication mechanism totally
    differs from table replication. While table replication sends
    changesets extracted from WAL records (i.e., changes are applied in
    commit LSN order), sequence replication
    synchronizes the subscriber's sequences with the publisher's current
    state. This raises an interesting theoretical question: In a scenario
    where we implement DDL replication (extracting and replicating DDL
    statements from WAL records to subscribers, as previously proposed),
    how would sequence-related DDL replication interact with the sequence
    synchronization mechanism implemented in this patch?
    
    Regards,
    
    --
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  297. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-08-18T09:13:13Z

    On Sat, 16 Aug 2025 at 14:15, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > As I understand it, the logical replication of sequences implemented
    > by these patches shares the same user interface as table replication
    > (utilizing CREATE PUBLICATION and CREATE SUBSCRIPTION commands for
    > configuration). However, the underlying replication mechanism totally
    > differs from table replication. While table replication sends
    > changesets extracted from WAL records (i.e., changes are applied in
    > commit LSN order), sequence replication
    > synchronizes the subscriber's sequences with the publisher's current
    > state. This raises an interesting theoretical question: In a scenario
    > where we implement DDL replication (extracting and replicating DDL
    > statements from WAL records to subscribers, as previously proposed),
    > how would sequence-related DDL replication interact with the sequence
    > synchronization mechanism implemented in this patch?
    
    The handling of sequence DDL should mirror how we manage table DDL:
    1. During CREATE SUBSCRIPTION - Create sequences along with
    tables—there’s no issue when initializing them during the initial
    sync.
    2. During Incremental Synchronization - Treat sequence changes like
    table changes:
    2.a Creating new sequences: Apply the creation on the subscriber side
    when the corresponding WAL record appears.
    2.b Dropping sequences: Handle drops in the same way they should
    propagate and execute on the subscriber.
    2.c. Handling Modifications to Existing Sequences
    Sequence DDL changes can lead to two different outcomes:
    i) No Conflict - If the change applies cleanly, accept and apply it immediately.
    ii) Conflict
    An example:
    CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    SELECT nextval('s1') — called several times, advancing the sequence
    ALTER SEQUENCE s1 MAXVALUE 12;
    -- Error:
    ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    
    In such conflict cases, we should consider using setval() with
    is_called = false to adjust the sequence safely and avoid errors.
    
    Thoughts?
    
    Regards,
    Vignesh
    
    
    
    
  298. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-08-18T10:06:45Z

    On Fri, 15 Aug 2025 at 16:46, Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > Dear Vignesh,
    >
    > Thanks for updating the patch. Here are my small comments:
    >
    > 01.
    > Per pgindent report, publicationcmds.c should be fixed.
    
    Modified
    
    > 02.
    > ```
    > +       ScanKeyInit(&skey[1],
    > +                               Anum_pg_subscription_rel_srsubstate,
    > +                               BTEqualStrategyNumber, F_CHARNE,
    > +                               CharGetDatum(SUBREL_STATE_READY));
    > ```
    >
    > I felt it is more natural to "srsubstate = 'i'", instead of "srsubstate <> 'r'"
    
    Modified
    
    > 03.
    > ```
    > +               table_close(sequence_rel, NoLock);
    > +       }
    > +
    > +       /* Cleanup */
    > +       systable_endscan(scan);
    > +       table_close(rel, AccessShareLock);
    > +
    > +       CommitTransactionCommand();
    > ```
    >
    > To clarify, can we release the sequence at the end of the inner loop?
    >
    > I found that sequence relation is closed (but not release the lock) then commit
    > the transaction once. This approach cannot avoid dropping it by concurrent
    > transactions, but maybe you did due to the performance reason. So...I felt we
    > may able to release bit earlier.
    
    Modified
    
    > 04.
    > ```
    > +                       sequence_rel = try_table_open(seqinfo->localrelid, RowExclusiveLock);
    > +
    > +                       /* Get the local sequence */
    > +                       tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    > +                       if (!sequence_rel || !HeapTupleIsValid(tup))
    > +                       {
    > +                               elog(LOG, "skip synchronization of sequence \"%s.%s\" because it has been dropped concurrently",
    > +                                        seqinfo->nspname, seqinfo->seqname);
    > +
    > +                               batch_skipped_count++;
    > +                               continue;
    > +                       }
    > ```
    >
    > a. Code comment can be atop try_table_open().
    > b. Isn't it enough to check HeapTupleIsValid() here?
    
    Modified
    
    > 05.
    > ```
    > +                       /* Update the sequence only if the parameters are identical */
    > +                       if (seqform->seqtypid == seqtypid &&
    > +                               seqform->seqmin == seqmin && seqform->seqmax == seqmax &&
    > +                               seqform->seqcycle == seqcycle &&
    > +                               seqform->seqstart == seqstart &&
    > +                               seqform->seqincrement == seqincrement)
    > ```
    >
    > I noticed that seqcache is not compared. Is there a reason?
    
    I felt we could go ahead and set the sequence value even if seqcache
    is different unlike the other sequence parameters. That is the reason
    I did not compare it. Thoughts?
    
    > 06.
    > ```
    > +       foreach_ptr(LogicalRepSequenceInfo, seq_info, sequences_to_copy)
    > +       {
    > +               pfree(seq_info->seqname);
    > +               pfree(seq_info->nspname);
    > +               pfree(seq_info);
    > +       }
    > ```
    >
    > Per comment atop foreach_delete_current(), we should not directly do pfree()
    > the entry. Can you use foreach_delete_current()? I.e.,
    
    Modified
    
    > 07.
    > ```
    >         foreach_ptr(LogicalRepSequenceInfo, seq_info, sequences_to_copy)
    >         {
    >                 pfree(seq_info->seqname);
    >                 pfree(seq_info->nspname);
    >
    >                 sequences_to_copy =
    >                         foreach_delete_current(sequences_to_copy, seq_info);
    >         }
    > ```
    
    Modified
    
    > 08.
    > ```
    > +$node_subscriber->init(allows_streaming => 'logical');
    > ```
    >
    > Actually no need to set to 'logical'.
    
    Modified
    
    Thanks for the comments, the updated version has the changes for the same.
    
    Regards,
    Vignesh
    
  299. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-08-18T23:21:20Z

    On Mon, Aug 18, 2025 at 2:13 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Sat, 16 Aug 2025 at 14:15, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > As I understand it, the logical replication of sequences implemented
    > > by these patches shares the same user interface as table replication
    > > (utilizing CREATE PUBLICATION and CREATE SUBSCRIPTION commands for
    > > configuration). However, the underlying replication mechanism totally
    > > differs from table replication. While table replication sends
    > > changesets extracted from WAL records (i.e., changes are applied in
    > > commit LSN order), sequence replication
    > > synchronizes the subscriber's sequences with the publisher's current
    > > state. This raises an interesting theoretical question: In a scenario
    > > where we implement DDL replication (extracting and replicating DDL
    > > statements from WAL records to subscribers, as previously proposed),
    > > how would sequence-related DDL replication interact with the sequence
    > > synchronization mechanism implemented in this patch?
    >
    > The handling of sequence DDL should mirror how we manage table DDL:
    > 1. During CREATE SUBSCRIPTION - Create sequences along with
    > tables—there’s no issue when initializing them during the initial
    > sync.
    > 2. During Incremental Synchronization - Treat sequence changes like
    > table changes:
    > 2.a Creating new sequences: Apply the creation on the subscriber side
    > when the corresponding WAL record appears.
    > 2.b Dropping sequences: Handle drops in the same way they should
    > propagate and execute on the subscriber.
    > 2.c. Handling Modifications to Existing Sequences
    > Sequence DDL changes can lead to two different outcomes:
    > i) No Conflict - If the change applies cleanly, accept and apply it immediately.
    > ii) Conflict
    > An example:
    > CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    > SELECT nextval('s1') — called several times, advancing the sequence
    > ALTER SEQUENCE s1 MAXVALUE 12;
    > -- Error:
    > ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    >
    > In such conflict cases, we should consider using setval() with
    > is_called = false to adjust the sequence safely and avoid errors.
    >
    > Thoughts?
    
    Thank you for the explanation.
    
    IIUC even with DDL replication support for sequences, users would
    still need to manage the order of DDL operations for sequences and
    their synchronization (specifically when executing the REFRESH
    PUBLICATION [SEQUENCE] command). For example, if a sequence is dropped
    on the publisher, the subscriber would encounter synchronization
    failures unless the DROP SEQUENCE is properly applied. This potential
    issue concerns me.
    
    I recall that Amit initially proposed an approach involving a special
    NOOP record to enable the walsender to read and transmit sequence data
    to the subscriber[1]. Have you considered incorporating this concept
    into the current implementation? Under this approach, REFRESH
    PUBLICATION [SEQUENCE] would simply trigger the subscriber to write a
    special WAL record for sequence synchronization. Subsequently, when
    decoding the WAL record, the walsender would collect sequence data
    associated with its publications and transmit it to the subscriber.
    The apply worker would then process sequence changes in the same
    manner as table changes.
    
    We could potentially optimize this process by including the LSN of the
    last sequence synchronization in the WAL record, allowing the
    walsender to transmit only those sequences whose page LSN exceeds this
    value.
    
    This thread is quite long so I may have missed some previous
    discussion of these points, so I apologize if these matters have
    already been addressed.
    
    Regards,
    
    [1] https://www.postgresql.org/message-id/CAA4eK1LC%2BKJiAkSrpE_NwvNdidw9F2os7GERUeSxSKv71gXysQ%40mail.gmail.com
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  300. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-08-19T01:17:09Z

    On Mon, Aug 18, 2025 at 4:21 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > For example, if a sequence is dropped
    > on the publisher, the subscriber would encounter synchronization
    > failures unless the DROP SEQUENCE is properly applied.
    
    This example is wrong. It seems DROP SEQUENCE works but we might have
    problems with ALTER SEQUENCE.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  301. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-08-19T08:43:52Z

    On Tue, 19 Aug 2025 at 06:47, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Mon, Aug 18, 2025 at 4:21 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > For example, if a sequence is dropped
    > > on the publisher, the subscriber would encounter synchronization
    > > failures unless the DROP SEQUENCE is properly applied.
    >
    > This example is wrong. It seems DROP SEQUENCE works but we might have
    > problems with ALTER SEQUENCE.
    
    I also felt that DROP SEQUENCE does not pose a problem.
    
    When it comes to ALTER SEQUENCE, there are two distinct cases to consider:
    Case 1: Parameter Mismatch During REFRESH PUBLICATION SEQUENCES
    Example:
    -- Publisher
    CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    
    -- Subscriber
    CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    
    -- Publisher
    ALTER SEQUENCE s1 MAXVALUE 12;
    
    -- Subscriber
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    
    In this scenario, the refresh fails with an error because the sequence
    parameters no longer match:
    2025-08-19 12:41:52.289 IST [209043] ERROR:  logical replication
    sequence synchronization failed for subscription "sub1"
    2025-08-19 12:41:52.289 IST [209043] DETAIL:  Mismatched sequence(s)
    on subscriber: ("public.s1").
    2025-08-19 12:41:52.289 IST [209043] HINT:  For mismatched sequences,
    alter or re-create local sequences to have matching parameters as
    publishers.
    
    In this case, the user simply needs to update the subscriber sequence
    definition so that its parameters match the publisher.
    
    Case 2: Sequence value Conflict While Applying DDL Changes(Future patch)
    
    Example:
    -- Publisher
    CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    SELECT nextval('s1'); -- called several times, advancing sequence to 14
    
    -- Subscriber
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    SELECT currval('s1');
     currval
    ---------
          14
    
    Now on the publisher:
    SELECT setval('s1', 11);
    ALTER SEQUENCE s1 MAXVALUE 12;
    
    When applying the DDL change on the subscriber:
    ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    
    This illustrates a value conflict between the current state of the
    sequence on the subscriber and the altered definition from the
    publisher.
    
    For such cases, we could consider:
    Allowing the user to resolve the conflict manually, or
    Providing an option to reset the sequence automatically.
    
    A similar scenario can also occur with tables if a DML operation is
    executed on the subscriber.
    
    I’m still not entirely sure which of these scenarios you were referring to.
    Were you pointing to Case 2 (value conflict), or do you have another
    case in mind?
    
    Regards,
    Vignesh
    
    
    
    
  302. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-08-19T18:03:02Z

    On Tue, Aug 19, 2025 at 1:44 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 19 Aug 2025 at 06:47, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Mon, Aug 18, 2025 at 4:21 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > >
    > > > For example, if a sequence is dropped
    > > > on the publisher, the subscriber would encounter synchronization
    > > > failures unless the DROP SEQUENCE is properly applied.
    > >
    > > This example is wrong. It seems DROP SEQUENCE works but we might have
    > > problems with ALTER SEQUENCE.
    >
    > I also felt that DROP SEQUENCE does not pose a problem.
    >
    > When it comes to ALTER SEQUENCE, there are two distinct cases to consider:
    > Case 1: Parameter Mismatch During REFRESH PUBLICATION SEQUENCES
    > Example:
    > -- Publisher
    > CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    >
    > -- Subscriber
    > CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    >
    > -- Publisher
    > ALTER SEQUENCE s1 MAXVALUE 12;
    >
    > -- Subscriber
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    >
    > In this scenario, the refresh fails with an error because the sequence
    > parameters no longer match:
    > 2025-08-19 12:41:52.289 IST [209043] ERROR:  logical replication
    > sequence synchronization failed for subscription "sub1"
    > 2025-08-19 12:41:52.289 IST [209043] DETAIL:  Mismatched sequence(s)
    > on subscriber: ("public.s1").
    > 2025-08-19 12:41:52.289 IST [209043] HINT:  For mismatched sequences,
    > alter or re-create local sequences to have matching parameters as
    > publishers.
    >
    > In this case, the user simply needs to update the subscriber sequence
    > definition so that its parameters match the publisher.
    >
    > Case 2: Sequence value Conflict While Applying DDL Changes(Future patch)
    >
    > Example:
    > -- Publisher
    > CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    > SELECT nextval('s1'); -- called several times, advancing sequence to 14
    >
    > -- Subscriber
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > SELECT currval('s1');
    >  currval
    > ---------
    >       14
    >
    > Now on the publisher:
    > SELECT setval('s1', 11);
    > ALTER SEQUENCE s1 MAXVALUE 12;
    >
    > When applying the DDL change on the subscriber:
    > ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    >
    > This illustrates a value conflict between the current state of the
    > sequence on the subscriber and the altered definition from the
    > publisher.
    >
    > For such cases, we could consider:
    > Allowing the user to resolve the conflict manually, or
    > Providing an option to reset the sequence automatically.
    >
    > A similar scenario can also occur with tables if a DML operation is
    > executed on the subscriber.
    >
    > I’m still not entirely sure which of these scenarios you were referring to.
    > Were you pointing to Case 2 (value conflict), or do you have another
    > case in mind?
    
    I imagined something like case 2. For logical replication of tables,
    if we support DDL replication (i.e., CREATE/ALTER/DROP TABLE), all
    changes the apply worker executes are serialized in commit LSN order.
    Therefore, users would not have to be concerned about schema changes
    that happened to the publisher. On the other hand, for sequence
    replication, even if we support DDL replication for sequences (i.e.,
    CREATE/ALTER/DROP SEQUENCES), users would have to execute REFRESH
    PUBLICATION SEQUENCES command after "ALTER SEQUENCE s1 MAXVALUE 12;"
    has been replicated on the subscriber. Otherwise, REFRESH PUBLICATION
    SEQUENCE command would fail because the sequence parameters no longer
    match.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  303. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-08-20T04:14:24Z

    On Tue, Aug 19, 2025 at 11:33 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Tue, Aug 19, 2025 at 1:44 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > >
    > > Case 2: Sequence value Conflict While Applying DDL Changes(Future patch)
    > >
    > > Example:
    > > -- Publisher
    > > CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    > > SELECT nextval('s1'); -- called several times, advancing sequence to 14
    > >
    > > -- Subscriber
    > > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > > SELECT currval('s1');
    > >  currval
    > > ---------
    > >       14
    > >
    > > Now on the publisher:
    > > SELECT setval('s1', 11);
    > > ALTER SEQUENCE s1 MAXVALUE 12;
    > >
    > > When applying the DDL change on the subscriber:
    > > ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    > >
    > > This illustrates a value conflict between the current state of the
    > > sequence on the subscriber and the altered definition from the
    > > publisher.
    > >
    > > For such cases, we could consider:
    > > Allowing the user to resolve the conflict manually, or
    > > Providing an option to reset the sequence automatically.
    > >
    > > A similar scenario can also occur with tables if a DML operation is
    > > executed on the subscriber.
    > >
    > > I’m still not entirely sure which of these scenarios you were referring to.
    > > Were you pointing to Case 2 (value conflict), or do you have another
    > > case in mind?
    >
    > I imagined something like case 2. For logical replication of tables,
    > if we support DDL replication (i.e., CREATE/ALTER/DROP TABLE), all
    > changes the apply worker executes are serialized in commit LSN order.
    > Therefore, users would not have to be concerned about schema changes
    > that happened to the publisher. On the other hand, for sequence
    > replication, even if we support DDL replication for sequences (i.e.,
    > CREATE/ALTER/DROP SEQUENCES), users would have to execute REFRESH
    > PUBLICATION SEQUENCES command after "ALTER SEQUENCE s1 MAXVALUE 12;"
    > has been replicated on the subscriber. Otherwise, REFRESH PUBLICATION
    > SEQUENCE command would fail because the sequence parameters no longer
    > match.
    >
    
    In the example provided by Vignesh, it should do REFRESH before the
    ALTER SEQUENCE command; otherwise, the ALTER SEQUENCE won't be
    replicated, right? If so, I don't think we can do much with the design
    choice we made. During DDL replication of sequences, we need to
    consider it as a conflict.
    
    BTW, note that the same situation can happen even when the user
    manually changed the sequence value on the subscriber in some way. So,
    we can't prevent that.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  304. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-08-20T08:55:17Z

    On Tue, 19 Aug 2025 at 23:33, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > I imagined something like case 2. For logical replication of tables,
    > if we support DDL replication (i.e., CREATE/ALTER/DROP TABLE), all
    > changes the apply worker executes are serialized in commit LSN order.
    > Therefore, users would not have to be concerned about schema changes
    > that happened to the publisher. On the other hand, for sequence
    > replication, even if we support DDL replication for sequences (i.e.,
    > CREATE/ALTER/DROP SEQUENCES), users would have to execute REFRESH
    > PUBLICATION SEQUENCES command after "ALTER SEQUENCE s1 MAXVALUE 12;"
    > has been replicated on the subscriber. Otherwise, REFRESH PUBLICATION
    > SEQUENCE command would fail because the sequence parameters no longer
    > match.
    
    I am summarizing the challenges identified so far (assuming we have
    DDL replication implemented through WAL support)
    1) Lack of sequence-synchronization resulting in DDL replication
    failure/conflict.
    On the subscriber, the sequence has advanced to 14:
    SELECT currval('s1');
    currval
    ---------
         14
    
    On the publisher, the sequence is reset to 11 and MAXVALUE is changed to 12:
    SELECT setval('s1', 11);
    ALTER SEQUENCE s1 MAXVALUE 12;
    If the subscriber did not execute REFRESH PUBLICATION SEQUENCES, DDL
    replication will fail with error.
    ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    
    2) Manual DDL on subscriber resulting in sequence synchronization failure.
    On the subscriber, the sequence maxvalue is changed:
    ALTER SEQUENCE s1 MAXVALUE 12;
    
    On the publisher, the sequence has advanced to 14:
    SELECT currval('s1');
    currval
    ---------
         14
    
    REFRESH PUBLICATION SEQUENCES will fail because setting currvalue to
    14 is greater than the changed maxvalue 12 in the subscriber.
    
    3) Out of order DDL and REFRESH resulting in synchronization failure.
    Initially we have the same sequence on pub and sub. Then lets say pub
    has done parameter change:
    ALTER SEQUENCE s1 MAXVALUE 12;
    Now if this DDL is somehow not replicated on sub, REFRESH PUBLICATION
    SEQUENCES will fail initially and may work once DDL is replicated.
    ~~
    Problems 1 and 2 exist in both designs. While the WAL-based REFRESH
    may seem slightly better for Problem 3 since REFRESH on the subscriber
    will execute only after prior DDLs are replicated—even with the
    sequence-sync worker, this isn't a major issue. If a user triggers
    REFRESH before the DDL is replicated, the worker will refresh all
    sequences except the mismatched one, and keep restarting and retrying
    until the DDL is applied. Once that happens, the sequence sync
    completes automatically, without the user doing another REFRESH.
    Furthermore, the likelihood of a user executing REFRESH exactly during
    the window between the DDL execution on the publisher and its
    application on the subscriber seems relatively low.
    
    WAL-based approach OTOH introduces several additional challenges that
    may outweigh its potential benefits:
    1)  Increases load on WAL sender to collect sequence values. We are
    talking about all the sequences here which could be huge in number.
    2)  Table replication may stall until sequence conflicts are resolved.
    The  chances of hitting any conflict/error could be more here as
    compared to tables specially when sequence synchronization is not
    incremental and the number of sequences are huge. The continuous and
    more frequent errors if not handled by users may even end up
    invalidating the slot on primary.
    
    The worker approach neither blocks the apply worker in case of errors
    nor adds extra load on the WAL sender. On its own, Case 3 doesn’t seem
    significant enough to justify switching to a WAL-based design.
    Overall, the worker-based approach appears to be less complex and a
    better option.
    
    Regards,
    Vignesh
    
    
    
    
  305. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-08-20T11:57:18Z

    On Mon, Aug 18, 2025 at 3:36 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > Thanks for the comments, the updated version has the changes for the same.
    >
    
    I wanted to first discuss a few design points. The patch implements
    "ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES" such that it
    copies the existing sequences values and also adds/removes any missing
    sequences. For the second part (add/remove sequences), we already have
    a separate command "ALTER SUBSCRIPTION ... REFRESH PUBLICATION". So, I
    feel the new command should only copy the sequence values, as that
    will keep the interface easy to define and understand. Additionally,
    it will help to simplify the code in the patch, especially in the
    function AlterSubscription_refresh.
    
    We previously discussed *not* to launch an apply worker if the
    corresponding publication(s) only publish sequences. See [1]. We
    should consider it again to see if that is a good idea. It will have
    some drawbacks as compared to the current approach of doing sync via
    sync worker. The command could take time for a large number of
    sequences, and on failure, retry won't happen which can happen with
    background workers. Additionally, when the connect option is false for
    a subscription during creation, the user needs to later call REFRESH
    to sync the sequences after enabling the subscription. OTOH, doing the
    sync during the command will bring more predictability and simplify
    the patch. What do others think?
    
    A few other comments:
    1.
    If the publication includes tables as well,
    + * issue a warning.
    + */
    + if (!stmt->for_all_tables)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("WITH clause parameters are not supported for publications
    defined as FOR ALL SEQUENCES"));
    +
    + ereport(NOTICE,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("WITH clause parameters are not applicable to sequence
    synchronization and will be ignored"));
    
    Though we are issuing a NOTICE but the comment refers to WARNING.
    
    2.
    /*
    - * In case of ALTER SUBSCRIPTION ... REFRESH, subrel_local_oids contains
    - * the list of relation oids that are already present on the subscriber.
    - * This check should be skipped for these tables if checking for table
    - * sync scenario. However, when handling the retain_dead_tuples scenario,
    - * ensure all tables are checked, as some existing tables may now include
    - * changes from other origins due to newly created subscriptions on the
    - * publisher.
    + * In case of ALTER SUBSCRIPTION ... REFRESH PUBLICATION,
    + * subrel_local_oids contains the list of relation oids that are already
    + * present on the subscriber. This check should be skipped for these
    + * tables if checking for table sync scenario. However, when handling the
    + * retain_dead_tuples scenario, ensure all tables are checked, as some
    + * existing tables may now include changes from other origins due to newly
    + * created subscriptions on the publisher.
    
    IIUC, this and other similar comments and err_message changes are just
    using REFRESH PUBLICATION instead of REFRESH because now we have added
    a SEQUENCES alternative as well. If so, let's make this a refactoring
    patch for this just before the 0004 patch?
    
    3.
    ALTER_SUBSCRIPTION_DROP_PUBLICATION,
    - ALTER_SUBSCRIPTION_REFRESH,
    + ALTER_SUBSCRIPTION_REFRESH_PUBLICATION,
    + ALTER_SUBSCRIPTION_REFRESH_PUBLICATION_SEQUENCES,
    
    The length of the new type seems a bit longer. Can we try to slightly
    reduce it by using ALTER_SUBSCRIPTION_REFRESH_PUBLICATION_SEQ?
    
    4.
    + case ALTER_SUBSCRIPTION_REFRESH_PUBLICATION_SEQUENCES:
    + {
    + if (!sub->enabled)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES is not
    allowed for disabled subscriptions"));
    
    - AlterSubscription_refresh(sub, opts.copy_data, NULL);
    + PreventInTransactionBlock(isTopLevel, "ALTER SUBSCRIPTION ...
    REFRESH PUBLICATION SEQUENCES");
    
    Is there a need to restrict this new command in a transaction block?
    We restrict other commands because those can lead to a drop of slots
    that can't be rolled back whereas the sequencesync doesn't use slots,
    so it should be okay to allow this new command in the transaction
    block.
    
    5.
    static void
     AlterSubscription_refresh(Subscription *sub, bool copy_data,
    -   List *validate_publications)
    +   List *validate_publications, bool resync_all_sequences)
    …
    + if (resync_all_sequences)
    + {
    + UpdateSubscriptionRelState(sub->oid, relid, SUBREL_STATE_INIT,
    +    InvalidXLogRecPtr);
    …
    
    During refresh, we are re-initializing the sequence state by marking
    its previously synced LSN to InvalidXLogRecPtr and relation state as
    SUBREL_STATE_INIT. This will lose its previously synced value, and
    also changing it to SUBREL_STATE_INIT also doesn't sound intuitive,
    even though it serves the purpose. I feel it is better to use
    SUBREL_STATE_DATASYNC state as that indicates data is being
    synchronized, and let the LSN value be the same as the previous.
    
    [1]: https://www.postgresql.org/message-id/CAA4eK1LcBoPBCKa9yFOQnvpBv3a2ejf_EWC%3DZKksGcvqW7e0Zg%40mail.gmail.com
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  306. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-08-20T17:29:28Z

    On Tue, Aug 19, 2025 at 9:14 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Aug 19, 2025 at 11:33 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Tue, Aug 19, 2025 at 1:44 AM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > >
    > > > Case 2: Sequence value Conflict While Applying DDL Changes(Future patch)
    > > >
    > > > Example:
    > > > -- Publisher
    > > > CREATE SEQUENCE s1 MINVALUE 10 MAXVALUE 20;
    > > > SELECT nextval('s1'); -- called several times, advancing sequence to 14
    > > >
    > > > -- Subscriber
    > > > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > > > SELECT currval('s1');
    > > >  currval
    > > > ---------
    > > >       14
    > > >
    > > > Now on the publisher:
    > > > SELECT setval('s1', 11);
    > > > ALTER SEQUENCE s1 MAXVALUE 12;
    > > >
    > > > When applying the DDL change on the subscriber:
    > > > ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    > > >
    > > > This illustrates a value conflict between the current state of the
    > > > sequence on the subscriber and the altered definition from the
    > > > publisher.
    > > >
    > > > For such cases, we could consider:
    > > > Allowing the user to resolve the conflict manually, or
    > > > Providing an option to reset the sequence automatically.
    > > >
    > > > A similar scenario can also occur with tables if a DML operation is
    > > > executed on the subscriber.
    > > >
    > > > I’m still not entirely sure which of these scenarios you were referring to.
    > > > Were you pointing to Case 2 (value conflict), or do you have another
    > > > case in mind?
    > >
    > > I imagined something like case 2. For logical replication of tables,
    > > if we support DDL replication (i.e., CREATE/ALTER/DROP TABLE), all
    > > changes the apply worker executes are serialized in commit LSN order.
    > > Therefore, users would not have to be concerned about schema changes
    > > that happened to the publisher. On the other hand, for sequence
    > > replication, even if we support DDL replication for sequences (i.e.,
    > > CREATE/ALTER/DROP SEQUENCES), users would have to execute REFRESH
    > > PUBLICATION SEQUENCES command after "ALTER SEQUENCE s1 MAXVALUE 12;"
    > > has been replicated on the subscriber. Otherwise, REFRESH PUBLICATION
    > > SEQUENCE command would fail because the sequence parameters no longer
    > > match.
    > >
    >
    > In the example provided by Vignesh, it should do REFRESH before the
    > ALTER SEQUENCE command; otherwise, the ALTER SEQUENCE won't be
    > replicated, right?
    
    Not sure. The REFRESH command is specifically used to synchronize
    values (such as last_value) of the local sequence to the remote ones,
    but this only works when their definitions match. In contrast, DDL
    replication for sequences handles changes to the sequence definition
    itself. While DDLs are automatically replicated through logical
    replication based on WAL records, the REFRESH command requires manual
    execution by users. Therefore, I believe ALTER SEQUENCE statements
    would be replicated regardless of when users execute the REFRESH
    command. This means users would need to carefully consider the
    ordering of these operations to prevent potential conflicts.
    
    > If so, I don't think we can do much with the design
    > choice we made. During DDL replication of sequences, we need to
    > consider it as a conflict.
    >
    > BTW, note that the same situation can happen even when the user
    > manually changed the sequence value on the subscriber in some way. So,
    > we can't prevent that.
    
    Yes, I understand that conflicts can occur when users manually modify
    sequence values or parameters on the subscriber. However, in Vignesh's
    example, users are only executing the REFRESH command, without
    performing any ALTER SEQUENCE commands or setval() operations on the
    subscriber. In this scenario, I don't see why conflicts would arise
    even with DDL replication in place.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  307. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-08-21T04:04:40Z

    On Wed, Aug 20, 2025 at 11:00 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Tue, Aug 19, 2025 at 9:14 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > If so, I don't think we can do much with the design
    > > choice we made. During DDL replication of sequences, we need to
    > > consider it as a conflict.
    > >
    > > BTW, note that the same situation can happen even when the user
    > > manually changed the sequence value on the subscriber in some way. So,
    > > we can't prevent that.
    >
    > Yes, I understand that conflicts can occur when users manually modify
    > sequence values or parameters on the subscriber. However, in Vignesh's
    > example, users are only executing the REFRESH command, without
    > performing any ALTER SEQUENCE commands or setval() operations on the
    > subscriber. In this scenario, I don't see why conflicts would arise
    > even with DDL replication in place.
    >
    
    This is because DDL can also fail if the existing sequence data does
    not adhere to the DDL change. This will be true even for tables, but
    let's focus on the sequence case. See below part of the example:
    
    -- Subscriber
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    SELECT currval('s1');
    currval
    ---------
    14
    
    -- Now on the publisher:
    SELECT setval('s1', 11);
    ALTER SEQUENCE s1 MAXVALUE 12;
    
    When applying the DDL change on the subscriber:
    ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    
    Here the user has intentionally reduced the existing value of the
    sequence to (11) on the publisher after the REFRESH command and then
    performed a DDL that is compatible with the latest RESTART value (11).
    Now, because we did REFRESH before the user set the value of sequence
    as 11, the current value on the subscriber will be 14. When we
    replicate the DDL, it will find the latest RESTART value as (14)
    greater than DDL's changed MAXVALUE (12), so it will fail, and the
    subscriber will retry. Users have to manually perform REFRESH once
    again, or maybe as part of a conflict resolution strategy, we can do
    this internally. IIUC, we can't avoid this even if we start writing
    WAL for the REFRESH command on the publisher.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  308. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-08-21T06:19:08Z

    On Wed, Aug 20, 2025 at 2:25 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 19 Aug 2025 at 23:33, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > I imagined something like case 2. For logical replication of tables,
    > > if we support DDL replication (i.e., CREATE/ALTER/DROP TABLE), all
    > > changes the apply worker executes are serialized in commit LSN order.
    > > Therefore, users would not have to be concerned about schema changes
    > > that happened to the publisher. On the other hand, for sequence
    > > replication, even if we support DDL replication for sequences (i.e.,
    > > CREATE/ALTER/DROP SEQUENCES), users would have to execute REFRESH
    > > PUBLICATION SEQUENCES command after "ALTER SEQUENCE s1 MAXVALUE 12;"
    > > has been replicated on the subscriber. Otherwise, REFRESH PUBLICATION
    > > SEQUENCE command would fail because the sequence parameters no longer
    > > match.
    >
    > I am summarizing the challenges identified so far (assuming we have
    > DDL replication implemented through WAL support)
    > 1) Lack of sequence-synchronization resulting in DDL replication
    > failure/conflict.
    > On the subscriber, the sequence has advanced to 14:
    > SELECT currval('s1');
    > currval
    > ---------
    >      14
    >
    > On the publisher, the sequence is reset to 11 and MAXVALUE is changed to 12:
    > SELECT setval('s1', 11);
    > ALTER SEQUENCE s1 MAXVALUE 12;
    > If the subscriber did not execute REFRESH PUBLICATION SEQUENCES, DDL
    > replication will fail with error.
    > ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    >
    > 2) Manual DDL on subscriber resulting in sequence synchronization failure.
    > On the subscriber, the sequence maxvalue is changed:
    > ALTER SEQUENCE s1 MAXVALUE 12;
    >
    > On the publisher, the sequence has advanced to 14:
    > SELECT currval('s1');
    > currval
    > ---------
    >      14
    >
    > REFRESH PUBLICATION SEQUENCES will fail because setting currvalue to
    > 14 is greater than the changed maxvalue 12 in the subscriber.
    >
    > 3) Out of order DDL and REFRESH resulting in synchronization failure.
    > Initially we have the same sequence on pub and sub. Then lets say pub
    > has done parameter change:
    > ALTER SEQUENCE s1 MAXVALUE 12;
    > Now if this DDL is somehow not replicated on sub, REFRESH PUBLICATION
    > SEQUENCES will fail initially and may work once DDL is replicated.
    > ~~
    > Problems 1 and 2 exist in both designs. While the WAL-based REFRESH
    > may seem slightly better for Problem 3 since REFRESH on the subscriber
    > will execute only after prior DDLs are replicated—even with the
    > sequence-sync worker, this isn't a major issue. If a user triggers
    > REFRESH before the DDL is replicated, the worker will refresh all
    > sequences except the mismatched one, and keep restarting and retrying
    > until the DDL is applied. Once that happens, the sequence sync
    > completes automatically, without the user doing another REFRESH.
    > Furthermore, the likelihood of a user executing REFRESH exactly during
    > the window between the DDL execution on the publisher and its
    > application on the subscriber seems relatively low.
    >
    > WAL-based approach OTOH introduces several additional challenges that
    > may outweigh its potential benefits:
    > 1)  Increases load on WAL sender to collect sequence values. We are
    > talking about all the sequences here which could be huge in number.
    > 2)  Table replication may stall until sequence conflicts are resolved.
    > The  chances of hitting any conflict/error could be more here as
    > compared to tables specially when sequence synchronization is not
    > incremental and the number of sequences are huge. The continuous and
    > more frequent errors if not handled by users may even end up
    > invalidating the slot on primary.
    >
    > The worker approach neither blocks the apply worker in case of errors
    > nor adds extra load on the WAL sender. On its own, Case 3 doesn’t seem
    > significant enough to justify switching to a WAL-based design.
    > Overall, the worker-based approach appears to be less complex and a
    > better option.
    >
    
    Agree on this. Please find a few comments on the previous patch:
    
    
    1)
    +        Returns information about the sequence. <literal>last_value</literal>
    +        last sequence value set in sequence by nextval or setval,
    
    <literal>last_value</literal> indicates ....
    
    2)
    + * If 'resync_all_sequences' is true:
    + *     Perform the above operation only for sequences.
    
    Shall we update:
      Perform the above operation only for sequences and resync all the
      sequences including existing ones.
    
    <old comment, I think somehow missed to be addressed.>
    
    3)
    + check_and_launch_sync_worker(nsyncworkers, InvalidOid,
    + &MyLogicalRepWorker->last_seqsync_start_time);
    
    Shall we simply name it as 'launch_sync_worker'.
    'check' looks a little odd. All such functions (ex:
    logicalrep_worker_launch) has internal checks but the name need not to
    have 'check' keyword
    
    4)
    + * Attempt to launch a sync worker (sequence or table) if there is a worker
    + * available and the retry interval has elapsed.
    
    shall we say:
    'if there is a sync worker slot available' instead of 'if there is a
    worker available'
    
    5)
    copy_sequences:
    + if (!sequence_rel || !HeapTupleIsValid(tup))
    + {
    + elog(LOG, "skip synchronization of sequence \"%s.%s\" because it has
    been dropped concurrently",
    + seqinfo->nspname, seqinfo->seqname);
    +
    + batch_skipped_count++;
    + continue;
    + }
    
    Is it possible that sequence_rel is valid while tuple is not? If
    possible, then do we need table_close before continuing?
    
    6)
    In copy_sequences() wherever we are using seqinfo->nspname,
    seqinfo->seqname; shall we directly use local vars nspname, seqname.
    
    7)
    LogicalRepSyncSequences:
    + /* Skip if sequence was dropped concurrently */
    + sequence_rel = try_table_open(subrel->srrelid, RowExclusiveLock);
    + if (!sequence_rel)
    + continue;
    
    Here we are not checking tuple-validity like we did in copy_sequences
    (comment 5 above). I think this alone should suffice even in
    copy_sequences(). What do you think?
    
    thanks
    Shveta
    
    
    
    
  309. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-08-21T16:38:42Z

    On Thu, 21 Aug 2025 at 11:49, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Wed, Aug 20, 2025 at 2:25 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Tue, 19 Aug 2025 at 23:33, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > >
    > > > I imagined something like case 2. For logical replication of tables,
    > > > if we support DDL replication (i.e., CREATE/ALTER/DROP TABLE), all
    > > > changes the apply worker executes are serialized in commit LSN order.
    > > > Therefore, users would not have to be concerned about schema changes
    > > > that happened to the publisher. On the other hand, for sequence
    > > > replication, even if we support DDL replication for sequences (i.e.,
    > > > CREATE/ALTER/DROP SEQUENCES), users would have to execute REFRESH
    > > > PUBLICATION SEQUENCES command after "ALTER SEQUENCE s1 MAXVALUE 12;"
    > > > has been replicated on the subscriber. Otherwise, REFRESH PUBLICATION
    > > > SEQUENCE command would fail because the sequence parameters no longer
    > > > match.
    > >
    > > I am summarizing the challenges identified so far (assuming we have
    > > DDL replication implemented through WAL support)
    > > 1) Lack of sequence-synchronization resulting in DDL replication
    > > failure/conflict.
    > > On the subscriber, the sequence has advanced to 14:
    > > SELECT currval('s1');
    > > currval
    > > ---------
    > >      14
    > >
    > > On the publisher, the sequence is reset to 11 and MAXVALUE is changed to 12:
    > > SELECT setval('s1', 11);
    > > ALTER SEQUENCE s1 MAXVALUE 12;
    > > If the subscriber did not execute REFRESH PUBLICATION SEQUENCES, DDL
    > > replication will fail with error.
    > > ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    > >
    > > 2) Manual DDL on subscriber resulting in sequence synchronization failure.
    > > On the subscriber, the sequence maxvalue is changed:
    > > ALTER SEQUENCE s1 MAXVALUE 12;
    > >
    > > On the publisher, the sequence has advanced to 14:
    > > SELECT currval('s1');
    > > currval
    > > ---------
    > >      14
    > >
    > > REFRESH PUBLICATION SEQUENCES will fail because setting currvalue to
    > > 14 is greater than the changed maxvalue 12 in the subscriber.
    > >
    > > 3) Out of order DDL and REFRESH resulting in synchronization failure.
    > > Initially we have the same sequence on pub and sub. Then lets say pub
    > > has done parameter change:
    > > ALTER SEQUENCE s1 MAXVALUE 12;
    > > Now if this DDL is somehow not replicated on sub, REFRESH PUBLICATION
    > > SEQUENCES will fail initially and may work once DDL is replicated.
    > > ~~
    > > Problems 1 and 2 exist in both designs. While the WAL-based REFRESH
    > > may seem slightly better for Problem 3 since REFRESH on the subscriber
    > > will execute only after prior DDLs are replicated—even with the
    > > sequence-sync worker, this isn't a major issue. If a user triggers
    > > REFRESH before the DDL is replicated, the worker will refresh all
    > > sequences except the mismatched one, and keep restarting and retrying
    > > until the DDL is applied. Once that happens, the sequence sync
    > > completes automatically, without the user doing another REFRESH.
    > > Furthermore, the likelihood of a user executing REFRESH exactly during
    > > the window between the DDL execution on the publisher and its
    > > application on the subscriber seems relatively low.
    > >
    > > WAL-based approach OTOH introduces several additional challenges that
    > > may outweigh its potential benefits:
    > > 1)  Increases load on WAL sender to collect sequence values. We are
    > > talking about all the sequences here which could be huge in number.
    > > 2)  Table replication may stall until sequence conflicts are resolved.
    > > The  chances of hitting any conflict/error could be more here as
    > > compared to tables specially when sequence synchronization is not
    > > incremental and the number of sequences are huge. The continuous and
    > > more frequent errors if not handled by users may even end up
    > > invalidating the slot on primary.
    > >
    > > The worker approach neither blocks the apply worker in case of errors
    > > nor adds extra load on the WAL sender. On its own, Case 3 doesn’t seem
    > > significant enough to justify switching to a WAL-based design.
    > > Overall, the worker-based approach appears to be less complex and a
    > > better option.
    > >
    >
    > Agree on this. Please find a few comments on the previous patch:
    >
    >
    > 1)
    > +        Returns information about the sequence. <literal>last_value</literal>
    > +        last sequence value set in sequence by nextval or setval,
    >
    > <literal>last_value</literal> indicates ....
    
    Modified
    
    > 2)
    > + * If 'resync_all_sequences' is true:
    > + *     Perform the above operation only for sequences.
    >
    > Shall we update:
    >   Perform the above operation only for sequences and resync all the
    >   sequences including existing ones.
    >
    > <old comment, I think somehow missed to be addressed.>
    
    This code is removed now
    
    > 3)
    > + check_and_launch_sync_worker(nsyncworkers, InvalidOid,
    > + &MyLogicalRepWorker->last_seqsync_start_time);
    >
    > Shall we simply name it as 'launch_sync_worker'.
    > 'check' looks a little odd. All such functions (ex:
    > logicalrep_worker_launch) has internal checks but the name need not to
    > have 'check' keyword
    
    Modified
    
    > 4)
    > + * Attempt to launch a sync worker (sequence or table) if there is a worker
    > + * available and the retry interval has elapsed.
    >
    > shall we say:
    > 'if there is a sync worker slot available' instead of 'if there is a
    > worker available'
    
    Modified
    
    > 5)
    > copy_sequences:
    > + if (!sequence_rel || !HeapTupleIsValid(tup))
    > + {
    > + elog(LOG, "skip synchronization of sequence \"%s.%s\" because it has
    > been dropped concurrently",
    > + seqinfo->nspname, seqinfo->seqname);
    > +
    > + batch_skipped_count++;
    > + continue;
    > + }
    >
    > Is it possible that sequence_rel is valid while tuple is not? If
    > possible, then do we need table_close before continuing?
    
    I felt it is not possible as the lock on sequence has been acquired
    successfully.
    
    > 6)
    > In copy_sequences() wherever we are using seqinfo->nspname,
    > seqinfo->seqname; shall we directly use local vars nspname, seqname.
    
    Modified
    
    > 7)
    > LogicalRepSyncSequences:
    > + /* Skip if sequence was dropped concurrently */
    > + sequence_rel = try_table_open(subrel->srrelid, RowExclusiveLock);
    > + if (!sequence_rel)
    > + continue;
    >
    > Here we are not checking tuple-validity like we did in copy_sequences
    > (comment 5 above). I think this alone should suffice even in
    > copy_sequences(). What do you think?
    
    In this case we just need the sequence and schema name which is
    available in sequence_rel whereas in case of copy_sequences we need
    other sequence parameters like min, max, cycle etc which requires the
    tuple. I felt the existing code is ok.
    
    I have also addressed all the comments from [1] in the attached
    v20250823 version patch.
    [1] - https://www.postgresql.org/message-id/CAA4eK1%2BoVQW8oP%3DLo1X8qac6dzg-fgGQ6R_F_psfokUEqe%2Ba6w%40mail.gmail.com
    
    Regards,
    Vignesh
    
  310. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-08-21T17:22:10Z

    On Wed, Aug 20, 2025 at 9:04 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Wed, Aug 20, 2025 at 11:00 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Tue, Aug 19, 2025 at 9:14 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > If so, I don't think we can do much with the design
    > > > choice we made. During DDL replication of sequences, we need to
    > > > consider it as a conflict.
    > > >
    > > > BTW, note that the same situation can happen even when the user
    > > > manually changed the sequence value on the subscriber in some way. So,
    > > > we can't prevent that.
    > >
    > > Yes, I understand that conflicts can occur when users manually modify
    > > sequence values or parameters on the subscriber. However, in Vignesh's
    > > example, users are only executing the REFRESH command, without
    > > performing any ALTER SEQUENCE commands or setval() operations on the
    > > subscriber. In this scenario, I don't see why conflicts would arise
    > > even with DDL replication in place.
    > >
    >
    > This is because DDL can also fail if the existing sequence data does
    > not adhere to the DDL change. This will be true even for tables, but
    > let's focus on the sequence case. See below part of the example:
    >
    > -- Subscriber
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > SELECT currval('s1');
    > currval
    > ---------
    > 14
    >
    > -- Now on the publisher:
    > SELECT setval('s1', 11);
    > ALTER SEQUENCE s1 MAXVALUE 12;
    >
    > When applying the DDL change on the subscriber:
    > ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    >
    > Here the user has intentionally reduced the existing value of the
    > sequence to (11) on the publisher after the REFRESH command and then
    > performed a DDL that is compatible with the latest RESTART value (11).
    > Now, because we did REFRESH before the user set the value of sequence
    > as 11, the current value on the subscriber will be 14. When we
    > replicate the DDL, it will find the latest RESTART value as (14)
    > greater than DDL's changed MAXVALUE (12), so it will fail, and the
    > subscriber will retry. Users have to manually perform REFRESH once
    > again, or maybe as part of a conflict resolution strategy, we can do
    > this internally. IIUC, we can't avoid this even if we start writing
    > WAL for the REFRESH command on the publisher.
    
    Right. Since DMLs and DDLs for sequences are replicated and applied to
    the subscriber out of order even if we write WAL for the REFRESH
    command.
    
    On the other hand, there is a scenario where we can cover with the
    idea of writing a WAL for the REFRESH command:
    
    -- Publisher
    CREATE s as integer;
    select setval('s', pow(2,31)::int)
    
    -- Subscriber
    CREATE s as integer;
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    -- the last value of 's' is 1073741824
    
    -- Publisher
    alter sequence s as bigint;
    select setval('s', pow(2,50)::bigint);
    
    -- Subscriber
    ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    -- sequence synchronization keeps failing due to mismatch sequence
    definition until ALTER SEQUENCE DDL is applied to the subscriber.
    
    I'm not suggesting to change the current approach but I'd just like to
    figure out how sequence replication will work with future DDL
    replication if we implement sequence synchronization as a logical
    replication feature.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  311. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-08-22T04:08:25Z

    On Thu, Aug 21, 2025 at 10:52 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Wed, Aug 20, 2025 at 9:04 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Wed, Aug 20, 2025 at 11:00 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > > >
    > > > On Tue, Aug 19, 2025 at 9:14 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > > > If so, I don't think we can do much with the design
    > > > > choice we made. During DDL replication of sequences, we need to
    > > > > consider it as a conflict.
    > > > >
    > > > > BTW, note that the same situation can happen even when the user
    > > > > manually changed the sequence value on the subscriber in some way. So,
    > > > > we can't prevent that.
    > > >
    > > > Yes, I understand that conflicts can occur when users manually modify
    > > > sequence values or parameters on the subscriber. However, in Vignesh's
    > > > example, users are only executing the REFRESH command, without
    > > > performing any ALTER SEQUENCE commands or setval() operations on the
    > > > subscriber. In this scenario, I don't see why conflicts would arise
    > > > even with DDL replication in place.
    > > >
    > >
    > > This is because DDL can also fail if the existing sequence data does
    > > not adhere to the DDL change. This will be true even for tables, but
    > > let's focus on the sequence case. See below part of the example:
    > >
    > > -- Subscriber
    > > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > > SELECT currval('s1');
    > > currval
    > > ---------
    > > 14
    > >
    > > -- Now on the publisher:
    > > SELECT setval('s1', 11);
    > > ALTER SEQUENCE s1 MAXVALUE 12;
    > >
    > > When applying the DDL change on the subscriber:
    > > ERROR:  RESTART value (14) cannot be greater than MAXVALUE (12)
    > >
    > > Here the user has intentionally reduced the existing value of the
    > > sequence to (11) on the publisher after the REFRESH command and then
    > > performed a DDL that is compatible with the latest RESTART value (11).
    > > Now, because we did REFRESH before the user set the value of sequence
    > > as 11, the current value on the subscriber will be 14. When we
    > > replicate the DDL, it will find the latest RESTART value as (14)
    > > greater than DDL's changed MAXVALUE (12), so it will fail, and the
    > > subscriber will retry. Users have to manually perform REFRESH once
    > > again, or maybe as part of a conflict resolution strategy, we can do
    > > this internally. IIUC, we can't avoid this even if we start writing
    > > WAL for the REFRESH command on the publisher.
    >
    > Right. Since DMLs and DDLs for sequences are replicated and applied to
    > the subscriber out of order even if we write WAL for the REFRESH
    > command.
    >
    > On the other hand, there is a scenario where we can cover with the
    > idea of writing a WAL for the REFRESH command:
    >
    > -- Publisher
    > CREATE s as integer;
    > select setval('s', pow(2,31)::int)
    >
    > -- Subscriber
    > CREATE s as integer;
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > -- the last value of 's' is 1073741824
    >
    > -- Publisher
    > alter sequence s as bigint;
    > select setval('s', pow(2,50)::bigint);
    >
    > -- Subscriber
    > ALTER SUBSCRIPTION sub1 REFRESH PUBLICATION SEQUENCES;
    > -- sequence synchronization keeps failing due to mismatch sequence
    > definition until ALTER SEQUENCE DDL is applied to the subscriber.
    >
    > I'm not suggesting to change the current approach but I'd just like to
    > figure out how sequence replication will work with future DDL
    > replication if we implement sequence synchronization as a logical
    > replication feature.
    >
    
    I think we can have a conflict handler for
    sequence_definition_mismatch where either it LOGs such that the user
    needs to retry the operation after some time, or let it automatically
    wait and retry, or a combination of both. As we are already working on
    conflict handling (conflict detection, storage, and resolution), we
    will at least have a way to store and let users be aware of such a
    conflict, but in the best case, we will have conflict resolution as
    well by the time replication of DDL sequence will be in a position to
    land. Do you have better ideas?
    
    BTW, do you have any suggestions on the first two design points raised
    by me in email [1]?
    
    [1] - https://www.postgresql.org/message-id/CAA4eK1%2BoVQW8oP%3DLo1X8qac6dzg-fgGQ6R_F_psfokUEqe%2Ba6w%40mail.gmail.com
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  312. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-08-26T05:51:05Z

    On Thu, Aug 21, 2025 at 10:08 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    
    > I have also addressed all the comments from [1] in the attached
    > v20250823 version patch.
    > [1] - https://www.postgresql.org/message-id/CAA4eK1%2BoVQW8oP%3DLo1X8qac6dzg-fgGQ6R_F_psfokUEqe%2Ba6w%40mail.gmail.com
    >
    
    Thank You for the patches. I see a race condition between alter-seq and refresh.
    
    Say we have triggered REFRESH on sub, and when seq-sync worker is in
    copy_sequences() where it has retrieved the local sequence using
    seqname while it has not locked the sequence-relation yet, if
    meanwhile we alter sequence and change its name, seq-sync worker ends
    up syncing that renamed sequence values with old-fetched sequence.
    Steps:
    
    1) create a sequence seq0 on pub and sub
    2) do REFRESH PUBLICATION SEQ on sub
    3) In seq-sync worker, during copy_sequences() hold debugger at:
    seqinfo->remote_seq_fetched = true;
    4) rename sequence on sub :  ALTER SEQUENCE seq0 RENAME TO seq1;
    5) release debugger in seq-sync worker. It will end up syncing seq1
    using seq0 fetched from pub.
    
    thanks
    Shveta
    
    
    
    
  313. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-08-28T08:37:01Z

    Dear Shveta,
    
    > Say we have triggered REFRESH on sub, and when seq-sync worker is in
    > copy_sequences() where it has retrieved the local sequence using
    > seqname while it has not locked the sequence-relation yet, if
    > meanwhile we alter sequence and change its name, seq-sync worker ends
    > up syncing that renamed sequence values with old-fetched sequence.
    > Steps:
    
    Personally not sure it should be fixed. IIUC, this could happen because the
    sequence sync worker does not handle everything in the one transaction. However,
    the transaction would be quite longer if we modify that.
    
    From another perspective... assuming that the sequencesync worker has lock
    during the synchronization. In your workload, the ALTER SEQUENCE command would
    be delayed till the synchronization is done. In the end, the seq0 is synched
    with the pub's seq0 then renamed to seq1 - eventually there are the same result.
    Can you clarify if there are other problematic workloads?
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
  314. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-08-28T11:37:56Z

    Dear Vignesh,
    
    Thanks for updating the patch. Below are my comments.
    
    01.
    ```
    		/* Relation is either a sequence or a table */
    		relkind = get_rel_relkind(subrel->srrelid);
    		if (relkind != RELKIND_SEQUENCE)
    			continue;
    ```
    
    Can you update the comment to "Skip if the relation is not a sequence"?
    The current one seems not related with what we do.
    
    02.
    ```
    	appendStringInfo(&app_name, "%s_%s", MySubscription->name, "sequencesync worker");
    ```
    
    I'm wondering what is the good application_name. One idea is to follow the
    tablesync worker: "pg_%u_sequence_sync_%u_%llu", another one is to use the same
    name as bgwoker: "logical replication sequencesync worker for subscription %u".
    Your name is also valid but it looks quite different with other processes.
    Do others have any opinions?
    
    03.
    ```
    test_pub=# SELECT NEXTVAL('s1');
    ```
    I feel no need to be capital.
    
    04.
    ```
       <link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link> or
       <link linkend="sql-altersubscription-params-refresh-publication">
       <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</command></link> or
       <link linkend="sql-altersubscription-params-refresh-publication-sequences">
       <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES</command></link>.
    ```
    
    IIUC, we can use "A, B, or C" style.
    
    05.
    ```
    +        In logical replication, this parameter also limits how quickly a
    +        failing replication apply worker or table synchronization worker or
    +        sequence synchronization worker will be respawned.
    ```
    
    Same as above.
    
    06.
    ```
          <para>
           State codes for sequences:
           <literal>i</literal> = initialize,
           <literal>r</literal> = ready
          </para></entry>
    ```
    
    Now the attribute can be "d".
    
    07.
    
    I feel we should add notes for subscription options. e.g., binary option
    is no-op for sequence sync.
    
    08.
    ```
    	/* Get the list of tables and sequences from the publisher. */
    	if (server_version >= 190000)
    	{
    ```
    
    Not sure which is better, but I considered a way to append the string atop v16.
    Please see attached. How do you feel?
    
    09.
    fetch_relation_list() still has some "tables", which should be "relations".
    
    10.
    ```
    	if (sequencesync_worker)
    	{
    		/* Now safe to release the LWLock */
    		LWLockRelease(LogicalRepWorkerLock);
    		return;
    	}
    ```
    
    Not sure the comment is needed because the lock is acquired just above. Instead
    we can describe that sequence sync worker exists up to one per a subscription.
    
    11.
    Currently copy_sequences() does not check privilege within the function, it is
    done in SetSequence(). Basically it works well, but if the user does not have
    enough privilege, for one of the sequence in the batch, ERROR would be
    raised - all sequences cannot be synched. How about detecting it in the loop
    and skip synchronizing? This allows other sequences to be synced.
    
    12.
    ```
    	/*
    	 * This is a clean exit of the sequencesync worker; reset the
    	 * last_seqsync_start_time.
    	 */
    	logicalrep_reset_seqsync_start_time();
    ```
    
    ISTM the function can be used both sequence and table sync worker.
    
    13.
    ```
    		/* Fetch tables and sequences that are in non-ready state. */
    		rstates = GetSubscriptionRelations(MySubscription->oid, true, true,
    										   true);
    ```
    
    IIUC no need to check sequences if has_pending_sequences is NULL.
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
  315. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-01T05:39:31Z

    On Tue, 26 Aug 2025 at 11:21, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Thu, Aug 21, 2025 at 10:08 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    >
    > > I have also addressed all the comments from [1] in the attached
    > > v20250823 version patch.
    > > [1] - https://www.postgresql.org/message-id/CAA4eK1%2BoVQW8oP%3DLo1X8qac6dzg-fgGQ6R_F_psfokUEqe%2Ba6w%40mail.gmail.com
    > >
    >
    > Thank You for the patches. I see a race condition between alter-seq and refresh.
    >
    > Say we have triggered REFRESH on sub, and when seq-sync worker is in
    > copy_sequences() where it has retrieved the local sequence using
    > seqname while it has not locked the sequence-relation yet, if
    > meanwhile we alter sequence and change its name, seq-sync worker ends
    > up syncing that renamed sequence values with old-fetched sequence.
    > Steps:
    >
    > 1) create a sequence seq0 on pub and sub
    > 2) do REFRESH PUBLICATION SEQ on sub
    > 3) In seq-sync worker, during copy_sequences() hold debugger at:
    > seqinfo->remote_seq_fetched = true;
    > 4) rename sequence on sub :  ALTER SEQUENCE seq0 RENAME TO seq1;
    > 5) release debugger in seq-sync worker. It will end up syncing seq1
    > using seq0 fetched from pub.
    
    Thanks for reporting this, this is handled in the attached version of patch.
    
    Regards,
    Vignesh
    
  316. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-02T13:42:00Z

    On Thu, 28 Aug 2025 at 17:08, Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > Dear Vignesh,
    >
    > Thanks for updating the patch. Below are my comments.
    >
    > 01.
    > ```
    >                 /* Relation is either a sequence or a table */
    >                 relkind = get_rel_relkind(subrel->srrelid);
    >                 if (relkind != RELKIND_SEQUENCE)
    >                         continue;
    > ```
    >
    > Can you update the comment to "Skip if the relation is not a sequence"?
    > The current one seems not related with what we do.
    
    Modified
    
    > 02.
    > ```
    >         appendStringInfo(&app_name, "%s_%s", MySubscription->name, "sequencesync worker");
    > ```
    >
    > I'm wondering what is the good application_name. One idea is to follow the
    > tablesync worker: "pg_%u_sequence_sync_%u_%llu", another one is to use the same
    > name as bgwoker: "logical replication sequencesync worker for subscription %u".
    > Your name is also valid but it looks quite different with other processes.
    > Do others have any opinions?
    
    Modified
    
    > 03.
    > ```
    > test_pub=# SELECT NEXTVAL('s1');
    > ```
    > I feel no need to be capital.
    
    Modified
    
    > 04.
    > ```
    >    <link linkend="sql-createsubscription"><command>CREATE SUBSCRIPTION</command></link> or
    >    <link linkend="sql-altersubscription-params-refresh-publication">
    >    <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</command></link> or
    >    <link linkend="sql-altersubscription-params-refresh-publication-sequences">
    >    <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES</command></link>.
    > ```
    >
    > IIUC, we can use "A, B, or C" style.
    
    Modified
    
    > 05.
    > ```
    > +        In logical replication, this parameter also limits how quickly a
    > +        failing replication apply worker or table synchronization worker or
    > +        sequence synchronization worker will be respawned.
    > ```
    >
    > Same as above.
    
    Modified
    
    > 06.
    > ```
    >       <para>
    >        State codes for sequences:
    >        <literal>i</literal> = initialize,
    >        <literal>r</literal> = ready
    >       </para></entry>
    > ```
    >
    > Now the attribute can be "d".
    
    Modified
    
    > 07.
    >
    > I feel we should add notes for subscription options. e.g., binary option
    > is no-op for sequence sync.
    
    Modified
    
    > 08.
    > ```
    >         /* Get the list of tables and sequences from the publisher. */
    >         if (server_version >= 190000)
    >         {
    > ```
    >
    > Not sure which is better, but I considered a way to append the string atop v16.
    > Please see attached. How do you feel?
    
    Modified
    
    > 09.
    > fetch_relation_list() still has some "tables", which should be "relations".
    
    Modified
    
    > 10.
    > ```
    >         if (sequencesync_worker)
    >         {
    >                 /* Now safe to release the LWLock */
    >                 LWLockRelease(LogicalRepWorkerLock);
    >                 return;
    >         }
    > ```
    >
    > Not sure the comment is needed because the lock is acquired just above. Instead
    > we can describe that sequence sync worker exists up to one per a subscription.
    
    Removed this comment. I felt no need to add any additional comments here.
    
    > 11.
    > Currently copy_sequences() does not check privilege within the function, it is
    > done in SetSequence(). Basically it works well, but if the user does not have
    > enough privilege, for one of the sequence in the batch, ERROR would be
    > raised - all sequences cannot be synched. How about detecting it in the loop
    > and skip synchronizing? This allows other sequences to be synced.
    
    Currently we have missing sequences and mismatched sequences being
    printed at the end of the batch. We print the skip sequence because it
    is dropped concurrently or altered concurrently in the loop. Should we
    include this also in the loop itself? Based on it, I will change in
    next version.
    
    > 12.
    > ```
    >         /*
    >          * This is a clean exit of the sequencesync worker; reset the
    >          * last_seqsync_start_time.
    >          */
    >         logicalrep_reset_seqsync_start_time();
    > ```
    >
    > ISTM the function can be used both sequence and table sync worker.
    
    It is not required for table sync worker, for table sync worker it is
    maintained in last_start_times hash table.
    
    > 13.
    > ```
    >                 /* Fetch tables and sequences that are in non-ready state. */
    >                 rstates = GetSubscriptionRelations(MySubscription->oid, true, true,
    >                                                                                    true);
    > ```
    >
    > IIUC no need to check sequences if has_pending_sequences is NULL.
    
    I feel it is required, this is required to determine if a sequence
    sync worker should be started or not.
    
    Thanks for the comments, the attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  317. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-09-03T07:34:37Z

    Dear Vignesh,
    
    Thanks for updating the patch. Few comments:
    01.
    ```
    	/* Find the leader apply worker and signal it. */
    	logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    ```
    
    Sequencesync worker does not need to send a signal to the apply worker.
    Should we skip in the case?
    Per my understanding, the signal is being used to set the status to STATE_READY.
    
    02.
    ```
    	if (worker)
    		worker->last_seqsync_start_time = 0;
    
    	LWLockRelease(LogicalRepWorkerLock);
    ```
    
    I feel we can release LWLock first then update last_seqsync_start_time.
    
    03.
    Sequencesync worker cannot update its GUC parameters because ProcessConfigFile()
    is not called. How about checking the signal at the end of batch loop?
    
    04.
    ```
    			while (search_pos < total_seqs)
    			{
    				LogicalRepSequenceInfo *candidate_seq = lfirst(list_nth_cell(sequences_to_copy, search_pos));
    
    				if (!strcmp(candidate_seq->nspname, nspname) &&
    					!strcmp(candidate_seq->seqname, seqname))
    				{
    					seqinfo = candidate_seq;
    					search_pos++;
    					break;
    				}
    
    				search_pos++;
    			}
    ```
    
    It looks like that if the entry in sequences_to_copy is skipped, it won't be
    referred anymore. I feel this is method is bit dangerous, because ordering of
    the list may be different with the returned tuples from the publisher. Nodes may
    use the different collations.
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
  318. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-04T16:50:43Z

    On Wed, 3 Sept 2025 at 13:04, Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > Dear Vignesh,
    >
    > Thanks for updating the patch. Few comments:
    > 01.
    > ```
    >         /* Find the leader apply worker and signal it. */
    >         logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    > ```
    >
    > Sequencesync worker does not need to send a signal to the apply worker.
    > Should we skip in the case?
    > Per my understanding, the signal is being used to set the status to STATE_READY.
    
    Modified
    
    > 02.
    > ```
    >         if (worker)
    >                 worker->last_seqsync_start_time = 0;
    >
    >         LWLockRelease(LogicalRepWorkerLock);
    > ```
    >
    > I feel we can release LWLock first then update last_seqsync_start_time.
    
    I felt it should be done within lock so that
    ProcessSyncingSequencesForApply waits till the last_seqsync_start_time
    is also set.
    
    > 03.
    > Sequencesync worker cannot update its GUC parameters because ProcessConfigFile()
    > is not called. How about checking the signal at the end of batch loop?
    
    Modified
    
    > 04.
    > ```
    >                         while (search_pos < total_seqs)
    >                         {
    >                                 LogicalRepSequenceInfo *candidate_seq = lfirst(list_nth_cell(sequences_to_copy, search_pos));
    >
    >                                 if (!strcmp(candidate_seq->nspname, nspname) &&
    >                                         !strcmp(candidate_seq->seqname, seqname))
    >                                 {
    >                                         seqinfo = candidate_seq;
    >                                         search_pos++;
    >                                         break;
    >                                 }
    >
    >                                 search_pos++;
    >                         }
    > ```
    >
    > It looks like that if the entry in sequences_to_copy is skipped, it won't be
    > referred anymore. I feel this is method is bit dangerous, because ordering of
    > the list may be different with the returned tuples from the publisher. Nodes may
    > use the different collations.
    
    Modified
    
    The attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  319. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-09-04T21:34:19Z

    On Thu, Sep 4, 2025 at 9:51 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 3 Sept 2025 at 13:04, Hayato Kuroda (Fujitsu)
    > <kuroda.hayato@fujitsu.com> wrote:
    > >
    > > Dear Vignesh,
    > >
    > > Thanks for updating the patch. Few comments:
    > > 01.
    > > ```
    > >         /* Find the leader apply worker and signal it. */
    > >         logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    > > ```
    > >
    > > Sequencesync worker does not need to send a signal to the apply worker.
    > > Should we skip in the case?
    > > Per my understanding, the signal is being used to set the status to STATE_READY.
    >
    > Modified
    >
    > > 02.
    > > ```
    > >         if (worker)
    > >                 worker->last_seqsync_start_time = 0;
    > >
    > >         LWLockRelease(LogicalRepWorkerLock);
    > > ```
    > >
    > > I feel we can release LWLock first then update last_seqsync_start_time.
    >
    > I felt it should be done within lock so that
    > ProcessSyncingSequencesForApply waits till the last_seqsync_start_time
    > is also set.
    >
    > > 03.
    > > Sequencesync worker cannot update its GUC parameters because ProcessConfigFile()
    > > is not called. How about checking the signal at the end of batch loop?
    >
    > Modified
    >
    > > 04.
    > > ```
    > >                         while (search_pos < total_seqs)
    > >                         {
    > >                                 LogicalRepSequenceInfo *candidate_seq = lfirst(list_nth_cell(sequences_to_copy, search_pos));
    > >
    > >                                 if (!strcmp(candidate_seq->nspname, nspname) &&
    > >                                         !strcmp(candidate_seq->seqname, seqname))
    > >                                 {
    > >                                         seqinfo = candidate_seq;
    > >                                         search_pos++;
    > >                                         break;
    > >                                 }
    > >
    > >                                 search_pos++;
    > >                         }
    > > ```
    > >
    > > It looks like that if the entry in sequences_to_copy is skipped, it won't be
    > > referred anymore. I feel this is method is bit dangerous, because ordering of
    > > the list may be different with the returned tuples from the publisher. Nodes may
    > > use the different collations.
    >
    > Modified
    >
    > The attached patch has the changes for the same.
    
    Please rebase the patches as they conflict with current HEAD (due to
    commit 6359989654).
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  320. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-09-04T22:30:33Z

    On Wed, Aug 20, 2025 at 4:57 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Mon, Aug 18, 2025 at 3:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > Thanks for the comments, the updated version has the changes for the same.
    > >
    >
    > I wanted to first discuss a few design points. The patch implements
    > "ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES" such that it
    > copies the existing sequences values and also adds/removes any missing
    > sequences. For the second part (add/remove sequences), we already have
    > a separate command "ALTER SUBSCRIPTION ... REFRESH PUBLICATION". So, I
    > feel the new command should only copy the sequence values, as that
    > will keep the interface easy to define and understand. Additionally,
    > it will help to simplify the code in the patch, especially in the
    > function AlterSubscription_refresh.
    
    While I agree that the new command just copies the sequence values,
    I'm not sure the command should be implemented as an extension of
    ALTER SUBSCRIPTION ... REFRESH PUBLICATION command. Probably what the
    new command does is quite different from what REFRESH PUBLICATION
    command does?
    
    >
    > We previously discussed *not* to launch an apply worker if the
    > corresponding publication(s) only publish sequences. See [1]. We
    > should consider it again to see if that is a good idea. It will have
    > some drawbacks as compared to the current approach of doing sync via
    > sync worker. The command could take time for a large number of
    > sequences, and on failure, retry won't happen which can happen with
    > background workers. Additionally, when the connect option is false for
    > a subscription during creation, the user needs to later call REFRESH
    > to sync the sequences after enabling the subscription. OTOH, doing the
    > sync during the command will bring more predictability and simplify
    > the patch. What do others think?
    
    It seems okay to me that we launch an apply worker for a subscription
    corresponding to sequence-only publications. I think the situation
    seems somewhat similar to the case where we launch an apply worker
    even for a subscription corresponding to empty publications. It would
    be quite a rare case in practice where publications have only
    sequences. I guess that it would rather simplify the patch if we can
    cut the part of doing the sync during the command (i.e., not
    distinguish between table-and-sequence publications and sequence-only
    publications), no?
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  321. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-05T05:49:54Z

    On Fri, 5 Sept 2025 at 03:04, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > Please rebase the patches as they conflict with current HEAD (due to
    > commit 6359989654).
    
    Attached a rebased version of the patches.
    
    Regards,
    Vignesh
    
  322. Re: Logical Replication of sequences

    Chao Li <li.evan.chao@gmail.com> — 2025-09-05T08:24:12Z

    
    > On Sep 5, 2025, at 13:49, vignesh C <vignesh21@gmail.com> wrote:
    > 
    > On Fri, 5 Sept 2025 at 03:04, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >> 
    >> Please rebase the patches as they conflict with current HEAD (due to
    >> commit 6359989654).
    > 
    > Attached a rebased version of the patches.
    > 
    > Regards,
    > Vignesh
    > <v20250905-0001-Enhance-pg_get_sequence_data-function.patch><v20250905-0003-Reorganize-tablesync-Code-and-Introduce-sy.patch><v20250905-0002-Introduce-ALL-SEQUENCES-support-for-Postgr.patch><v20250905-0004-Update-ALTER-SUBSCRIPTION-REFRESH-to-ALTER.patch><v20250905-0005-Introduce-REFRESH-PUBLICATION-SEQUENCES-fo.patch><v20250905-0006-New-worker-for-sequence-synchronization-du.patch><v20250905-0007-Documentation-for-sequence-synchronization.patch>
    
    
    A few small comments:
    
    1 - 0001
    ```
    diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql
    index 2c220b60749..c8adddbfa31 100644
    --- a/src/test/regress/sql/sequence.sql
    +++ b/src/test/regress/sql/sequence.sql
    @@ -414,6 +414,6 @@ SELECT nextval('test_seq1');
     SELECT nextval('test_seq1');
     
     -- pg_get_sequence_data
    -SELECT * FROM pg_get_sequence_data('test_seq1');
    +SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
     
     DROP SEQUENCE test_seq1;
    ```
    
    As it shows log_cnt now, after calling pg_get_sequence_data(), I suggest add 8 nextval(), so that sequence goes to 11, and log_cnt should become to 22.
    
    2 - 0002
    ```
    -	if (schemaidlist && pubform->puballtables)
    +	pub_type = makeStringInfo();
    +
    +	appendStringInfo(pub_type, "%s", pubform->puballtables && pubform->puballsequences ? "FOR ALL TABLES, ALL SEQUENCES" :
    +					 pubform->puballtables ? "FOR ALL TABLES" : "FOR ALL SEQUENCES");
    +
    +	if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
     		ereport(ERROR,
     				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    -				 errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    -						NameStr(pubform->pubname)),
    -				 errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES publications.")));
    +				 errmsg("publication \"%s\" is defined as %s",
    +						NameStr(pubform->pubname), pub_type->data),
    +				 errdetail("Schemas cannot be added to or dropped from %s publications.", pub_type->data)));
    ```
    
    Here you build a string at runtime and inject it into log message, which seems to break some PG rules. In one of my previous review, I raised a comment for removing some duplicate code using this way, and get this info: https://www.postgresql.org/message-id/397c16a7-f57b-4f81-8497-6d692a9bf596%40eisentraut.org
    
    3 - 0005
    ```
    +		/*
    +		 * Skip sequence tuples. If even a single table tuple exists then the
    +		 * subscription has tables.
    +		 */
    +		if (get_rel_relkind(subrel->srrelid) != RELKIND_SEQUENCE)
    +		{
    +			has_subrels = true;
    +			break;
    +		}
    ```
    For publication, only valid relkind are RELKIND_RELATION, RELKIND_PARTITIONED_TABLE and newly added RELKIND_SEQUENCE. Here you want to check for table, using “!=  RELKIND_SEQUENCE” works. But I think doing “ kind == RELKIND_RELATION || kind == RELKIND_PARTITIONED_TABLE” is clearer and more reliable. Consider if some other kind is added, then “kind != RELKIND_SEQUENCE” might be broken, and hard to find the root cause.
    
    4 -0006
    ```
    -		appendStringInfo(&cmd, "SELECT DISTINCT n.nspname, c.relname, gpt.attrs\n"
    +		appendStringInfo(&cmd, "SELECT DISTINCT n.nspname, c.relname, gpt.attrs,  c.relkind\n"
    ```
    There is an extra whitespace before “c.relkind”.
    
    Best regards,
    --
    Chao Li (Evan)
    HighGo Software Co., Ltd.
    https://www.highgo.com/
    
    
    
    
    
  323. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-05T09:16:20Z

    On Fri, 5 Sept 2025 at 04:01, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Wed, Aug 20, 2025 at 4:57 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Mon, Aug 18, 2025 at 3:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > Thanks for the comments, the updated version has the changes for the same.
    > > >
    > >
    > > I wanted to first discuss a few design points. The patch implements
    > > "ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES" such that it
    > > copies the existing sequences values and also adds/removes any missing
    > > sequences. For the second part (add/remove sequences), we already have
    > > a separate command "ALTER SUBSCRIPTION ... REFRESH PUBLICATION". So, I
    > > feel the new command should only copy the sequence values, as that
    > > will keep the interface easy to define and understand. Additionally,
    > > it will help to simplify the code in the patch, especially in the
    > > function AlterSubscription_refresh.
    >
    > While I agree that the new command just copies the sequence values,
    > I'm not sure the command should be implemented as an extension of
    > ALTER SUBSCRIPTION ... REFRESH PUBLICATION command. Probably what the
    > new command does is quite different from what REFRESH PUBLICATION
    > command does?
    
    Alternatively, the syntax options could be:
    ALTER SUBSCRIPTION subname RESYNC PUBLICATION SEQUENCES;
    or
    ALTER SUBSCRIPTION subname RESYNC SEQUENCES;
    
    Do you have a preference between the two?
    
    > >
    > > We previously discussed *not* to launch an apply worker if the
    > > corresponding publication(s) only publish sequences. See [1]. We
    > > should consider it again to see if that is a good idea. It will have
    > > some drawbacks as compared to the current approach of doing sync via
    > > sync worker. The command could take time for a large number of
    > > sequences, and on failure, retry won't happen which can happen with
    > > background workers. Additionally, when the connect option is false for
    > > a subscription during creation, the user needs to later call REFRESH
    > > to sync the sequences after enabling the subscription. OTOH, doing the
    > > sync during the command will bring more predictability and simplify
    > > the patch. What do others think?
    >
    > It seems okay to me that we launch an apply worker for a subscription
    > corresponding to sequence-only publications. I think the situation
    > seems somewhat similar to the case where we launch an apply worker
    > even for a subscription corresponding to empty publications. It would
    > be quite a rare case in practice where publications have only
    > sequences.
    
    I agree with this.
    
    > I guess that it would rather simplify the patch if we can
    > cut the part of doing the sync during the command (i.e., not
    > distinguish between table-and-sequence publications and sequence-only
    > publications), no?
    
    Currently, we don’t make a distinction between the two. Just to
    clarify, could you point me to the specific part of the patch you’re
    referring to?
    
    Regards,
    Vignesh
    
    
    
    
  324. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-09-05T11:20:06Z

    On Fri, Sep 5, 2025 at 2:46 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 5 Sept 2025 at 04:01, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > On Wed, Aug 20, 2025 at 4:57 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Mon, Aug 18, 2025 at 3:36 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > Thanks for the comments, the updated version has the changes for the same.
    > > > >
    > > >
    > > > I wanted to first discuss a few design points. The patch implements
    > > > "ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES" such that it
    > > > copies the existing sequences values and also adds/removes any missing
    > > > sequences. For the second part (add/remove sequences), we already have
    > > > a separate command "ALTER SUBSCRIPTION ... REFRESH PUBLICATION". So, I
    > > > feel the new command should only copy the sequence values, as that
    > > > will keep the interface easy to define and understand. Additionally,
    > > > it will help to simplify the code in the patch, especially in the
    > > > function AlterSubscription_refresh.
    > >
    > > While I agree that the new command just copies the sequence values,
    > > I'm not sure the command should be implemented as an extension of
    > > ALTER SUBSCRIPTION ... REFRESH PUBLICATION command. Probably what the
    > > new command does is quite different from what REFRESH PUBLICATION
    > > command does?
    >
    > Alternatively, the syntax options could be:
    > ALTER SUBSCRIPTION subname RESYNC PUBLICATION SEQUENCES;
    > or
    > ALTER SUBSCRIPTION subname RESYNC SEQUENCES;
    >
    
    The other option on these lines is to use SYNC instead of RESYNC as
    for users RESYNC sounds more like redo where something has failed and
    we are trying to do it again. Also, this will be used even for the
    first time sync of sequences. I prefer the first alternative among
    these as having the PUBLICATION keyword suggests that we are syncing
    the sequences corresponding to all the publications that are part of
    subscription but I am okay with the second too.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  325. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-08T06:00:54Z

    On Fri, 5 Sept 2025 at 13:54, Chao Li <li.evan.chao@gmail.com> wrote:
    >
    >
    >
    > On Sep 5, 2025, at 13:49, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 5 Sept 2025 at 03:04, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    >
    > Please rebase the patches as they conflict with current HEAD (due to
    > commit 6359989654).
    >
    >
    > Attached a rebased version of the patches.
    >
    > Regards,
    > Vignesh
    > <v20250905-0001-Enhance-pg_get_sequence_data-function.patch><v20250905-0003-Reorganize-tablesync-Code-and-Introduce-sy.patch><v20250905-0002-Introduce-ALL-SEQUENCES-support-for-Postgr.patch><v20250905-0004-Update-ALTER-SUBSCRIPTION-REFRESH-to-ALTER.patch><v20250905-0005-Introduce-REFRESH-PUBLICATION-SEQUENCES-fo.patch><v20250905-0006-New-worker-for-sequence-synchronization-du.patch><v20250905-0007-Documentation-for-sequence-synchronization.patch>
    >
    >
    > A few small comments:
    >
    > 1 - 0001
    > ```
    > diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql
    > index 2c220b60749..c8adddbfa31 100644
    > --- a/src/test/regress/sql/sequence.sql
    > +++ b/src/test/regress/sql/sequence.sql
    > @@ -414,6 +414,6 @@ SELECT nextval('test_seq1');
    >  SELECT nextval('test_seq1');
    >
    >  -- pg_get_sequence_data
    > -SELECT * FROM pg_get_sequence_data('test_seq1');
    > +SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    >
    >  DROP SEQUENCE test_seq1;
    > ```
    >
    > As it shows log_cnt now, after calling pg_get_sequence_data(), I suggest add 8 nextval(), so that sequence goes to 11, and log_cnt should become to 22.
    
    Could you please explain the reason you’d like this to be done?
    
    > 2 - 0002
    > ```
    > - if (schemaidlist && pubform->puballtables)
    > + pub_type = makeStringInfo();
    > +
    > + appendStringInfo(pub_type, "%s", pubform->puballtables && pubform->puballsequences ? "FOR ALL TABLES, ALL SEQUENCES" :
    > + pubform->puballtables ? "FOR ALL TABLES" : "FOR ALL SEQUENCES");
    > +
    > + if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
    >   ereport(ERROR,
    >   (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > - errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    > - NameStr(pubform->pubname)),
    > - errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES publications.")));
    > + errmsg("publication \"%s\" is defined as %s",
    > + NameStr(pubform->pubname), pub_type->data),
    > + errdetail("Schemas cannot be added to or dropped from %s publications.", pub_type->data)));
    > ```
    >
    > Here you build a string at runtime and inject it into log message, which seems to break some PG rules. In one of my previous review, I raised a comment for removing some duplicate code using this way, and get this info: https://www.postgresql.org/message-id/397c16a7-f57b-4f81-8497-6d692a9bf596%40eisentraut.org
    
    Modified
    
    > 3 - 0005
    > ```
    > + /*
    > + * Skip sequence tuples. If even a single table tuple exists then the
    > + * subscription has tables.
    > + */
    > + if (get_rel_relkind(subrel->srrelid) != RELKIND_SEQUENCE)
    > + {
    > + has_subrels = true;
    > + break;
    > + }
    > ```
    > For publication, only valid relkind are RELKIND_RELATION, RELKIND_PARTITIONED_TABLE and newly added RELKIND_SEQUENCE. Here you want to check for table, using “!=  RELKIND_SEQUENCE” works. But I think doing “ kind == RELKIND_RELATION || kind == RELKIND_PARTITIONED_TABLE” is clearer and more reliable. Consider if some other kind is added, then “kind != RELKIND_SEQUENCE” might be broken, and hard to find the root cause.
    
    Modified
    
    > 4 -0006
    > ```
    > - appendStringInfo(&cmd, "SELECT DISTINCT n.nspname, c.relname, gpt.attrs\n"
    > + appendStringInfo(&cmd, "SELECT DISTINCT n.nspname, c.relname, gpt.attrs,  c.relkind\n"
    > ```
    > There is an extra whitespace before “c.relkind”.
    
    Modified
    
    Thanks for the comments, the attached v20250908 version patch has the
    changes for the same.
    
    Regards,
    Vignesh
    
  326. Re: Logical Replication of sequences

    Chao Li <li.evan.chao@gmail.com> — 2025-09-08T06:34:54Z

    
    > On Sep 8, 2025, at 14:00, vignesh C <vignesh21@gmail.com> wrote:
    >> 
    >> 
    >> 1 - 0001
    >> ```
    >> diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql
    >> index 2c220b60749..c8adddbfa31 100644
    >> --- a/src/test/regress/sql/sequence.sql
    >> +++ b/src/test/regress/sql/sequence.sql
    >> @@ -414,6 +414,6 @@ SELECT nextval('test_seq1');
    >> SELECT nextval('test_seq1');
    >> 
    >> -- pg_get_sequence_data
    >> -SELECT * FROM pg_get_sequence_data('test_seq1');
    >> +SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    >> 
    >> DROP SEQUENCE test_seq1;
    >> ```
    >> 
    >> As it shows log_cnt now, after calling pg_get_sequence_data(), I suggest add 8 nextval(), so that sequence goes to 11, and log_cnt should become to 22.
    > 
    > Could you please explain the reason you’d like this to be done?
    > 
    
    
    Because log_cnt is newly exposed, we want to verify its value in the test. When I first time ran the test code, I saw initial value of log_cnt was 32, then I thought log_cnt might get decreased if I ran nextval() again, but it didn’t. Only after I ran 10 (cache size) more nextval(), log_cnt got decreased by 10 to 22. The test code is a place for people to look for expected behavior. So I think adding more nextval() to verify and show the change of log_cnt is helpful.
    
    Best regards,
    --
    Chao Li (Evan)
    HighGo Software Co., Ltd.
    https://www.highgo.com/
    
    
    
    
    
  327. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-09T06:22:53Z

    On Mon, 8 Sept 2025 at 12:05, Chao Li <li.evan.chao@gmail.com> wrote:
    >
    >
    >
    > On Sep 8, 2025, at 14:00, vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    >
    > 1 - 0001
    > ```
    > diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql
    > index 2c220b60749..c8adddbfa31 100644
    > --- a/src/test/regress/sql/sequence.sql
    > +++ b/src/test/regress/sql/sequence.sql
    > @@ -414,6 +414,6 @@ SELECT nextval('test_seq1');
    > SELECT nextval('test_seq1');
    >
    > -- pg_get_sequence_data
    > -SELECT * FROM pg_get_sequence_data('test_seq1');
    > +SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    >
    > DROP SEQUENCE test_seq1;
    > ```
    >
    > As it shows log_cnt now, after calling pg_get_sequence_data(), I suggest add 8 nextval(), so that sequence goes to 11, and log_cnt should become to 22.
    >
    >
    > Could you please explain the reason you’d like this to be done?
    >
    >
    > Because log_cnt is newly exposed, we want to verify its value in the test. When I first time ran the test code, I saw initial value of log_cnt was 32, then I thought log_cnt might get decreased if I ran nextval() again, but it didn’t. Only after I ran 10 (cache size) more nextval(), log_cnt got decreased by 10 to 22. The test code is a place for people to look for expected behavior. So I think adding more nextval() to verify and show the change of log_cnt is helpful.
    
    Thanks, I will include this in the next version.
    
    Regards,
    Vignesh
    
    
    
    
  328. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-15T09:06:43Z

    On Mon, 8 Sept 2025 at 12:05, Chao Li <li.evan.chao@gmail.com> wrote:
    >
    >
    >
    > On Sep 8, 2025, at 14:00, vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    >
    > 1 - 0001
    > ```
    > diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql
    > index 2c220b60749..c8adddbfa31 100644
    > --- a/src/test/regress/sql/sequence.sql
    > +++ b/src/test/regress/sql/sequence.sql
    > @@ -414,6 +414,6 @@ SELECT nextval('test_seq1');
    > SELECT nextval('test_seq1');
    >
    > -- pg_get_sequence_data
    > -SELECT * FROM pg_get_sequence_data('test_seq1');
    > +SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    >
    > DROP SEQUENCE test_seq1;
    > ```
    >
    > As it shows log_cnt now, after calling pg_get_sequence_data(), I suggest add 8 nextval(), so that sequence goes to 11, and log_cnt should become to 22.
    >
    >
    > Could you please explain the reason you’d like this to be done?
    >
    >
    > Because log_cnt is newly exposed, we want to verify its value in the test. When I first time ran the test code, I saw initial value of log_cnt was 32, then I thought log_cnt might get decreased if I ran nextval() again, but it didn’t. Only after I ran 10 (cache size) more nextval(), log_cnt got decreased by 10 to 22. The test code is a place for people to look for expected behavior. So I think adding more nextval() to verify and show the change of log_cnt is helpful.
    
    This is addressed in the attached patch, also rebased the patch
    because of recent commits.
    
    Regards,
    Vignesh
    
  329. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-09-16T09:31:39Z

    On Mon, Sep 15, 2025 at 2:36 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > This is addressed in the attached patch, also rebased the patch
    > because of recent commits.
    >
    
    One of the patches conflict with recent commit 0d48d393 (launcher.c
    changes) and thus needs a rebase.
    
    thanks
    Shveta
    
    
    
    
  330. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2025-09-16T10:53:00Z

    On Mon, 15 Sept 2025 at 14:36, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 8 Sept 2025 at 12:05, Chao Li <li.evan.chao@gmail.com> wrote:
    > >
    > >
    > >
    > > On Sep 8, 2025, at 14:00, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > >
    > >
    > > 1 - 0001
    > > ```
    > > diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql
    > > index 2c220b60749..c8adddbfa31 100644
    > > --- a/src/test/regress/sql/sequence.sql
    > > +++ b/src/test/regress/sql/sequence.sql
    > > @@ -414,6 +414,6 @@ SELECT nextval('test_seq1');
    > > SELECT nextval('test_seq1');
    > >
    > > -- pg_get_sequence_data
    > > -SELECT * FROM pg_get_sequence_data('test_seq1');
    > > +SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    > >
    > > DROP SEQUENCE test_seq1;
    > > ```
    > >
    > > As it shows log_cnt now, after calling pg_get_sequence_data(), I suggest add 8 nextval(), so that sequence goes to 11, and log_cnt should become to 22.
    > >
    > >
    > > Could you please explain the reason you’d like this to be done?
    > >
    > >
    > > Because log_cnt is newly exposed, we want to verify its value in the test. When I first time ran the test code, I saw initial value of log_cnt was 32, then I thought log_cnt might get decreased if I ran nextval() again, but it didn’t. Only after I ran 10 (cache size) more nextval(), log_cnt got decreased by 10 to 22. The test code is a place for people to look for expected behavior. So I think adding more nextval() to verify and show the change of log_cnt is helpful.
    >
    > This is addressed in the attached patch, also rebased the patch
    > because of recent commits.
    >
    Hi Vignesh,
    
    FYI: the patches are not applying on current HEAD.
    
    I have reviewed the patches and here are my comments:
    
    1. For patch 0001:
    The 'log_cnt' column of 'pg_get_sequence_data' gets reset after a checkpoint.
    For example:
    postgres=# select * from pg_get_sequence_data('seq1');
     last_value | is_called | log_cnt |  page_lsn
    ------------+-----------+---------+------------
              3 | t         |      31 | 0/0177C800
    (1 row)
    postgres=# checkpoint;
    CHECKPOINT
    postgres=# select nextval('seq1');
     nextval
    ---------
           4
    (1 row)
    postgres=# select * from pg_get_sequence_data('seq1');
     last_value | is_called | log_cnt |  page_lsn
    ------------+-----------+---------+------------
              4 | t         |      32 | 0/0177C998
    
    So, for tests:
    +SELECT last_value, is_called, log_cnt, page_lsn <=
    pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    + last_value | is_called | log_cnt | lsn
    +------------+-----------+---------+-----
    +         20 | t         |      22 | t
    
    Is there a possibility that it can show a different value of "log_cnt"
    due checkpoint running in background or parallel test?
    
    I see following comment in the similar test:
    -- log_cnt can be higher if there is a checkpoint just at the right
    -- time, so just test for the expected range
    SELECT last_value, log_cnt IN (31, 32) AS log_cnt_ok, is_called FROM
    foo_seq_new;
    
    Thoughts?
    
    2. For patch 0002:
    I created a publication pub1 for all sequences, and now altering with
    set give following error:
    postgres=# alter publication pub1 SET (publish_via_partition_root);
    ERROR:  WITH clause parameters are not supported for publications
    defined as FOR ALL SEQUENCES
    
    I think we should not use "WITH clause parameters" for "ALTER
    PUBLICATION ... SET .." command.
    
    3. For patch 0003:
    We need to update the function 'HasSubscriptionRelationsCached'.
    It has function call "has_subrels = FetchTableStates(&started_tx)"
    
    I think FetchTableStates should be updated toFetchRelationStates.
    This function call was added in the recent commit [1].
    
    4. For patch 0007:
    We should update the logical-replication.sgml for the occurrence of with \dRp+:
    
    <programlisting><![CDATA[
    /* pub # */ \dRp+
                                             Publication p1
      Owner   | All tables | Inserts | Updates | Deletes | Truncates |
    Generated columns | Via root
    ----------+------------+---------+---------+---------+-----------+-------------------+----------
     postgres | f          | t       | t       | t       | t         |
    none              | f
    Tables:
        "public.t1" WHERE ((a > 5) AND (c = 'NSW'::text))
    
                                             Publication p2
      Owner   | All tables | Inserts | Updates | Deletes | Truncates |
    Generated columns | Via root
    ----------+------------+---------+---------+---------+-----------+-------------------+----------
     postgres | f          | t       | t       | t       | t         |
    none              | f
    Tables:
        "public.t1"
        "public.t2" WHERE (e = 99)
    
                                             Publication p3
      Owner   | All tables | Inserts | Updates | Deletes | Truncates |
    Generated columns | Via root
    ----------+------------+---------+---------+---------+-----------+-------------------+----------
     postgres | f          | t       | t       | t       | t         |
    none              | f
    
    
    [1]: https://github.com/postgres/postgres/commit/1f7e9ba3ac4eff13041abcc4c9c517ad835fa449
    
    Thanks,
    Shlok Kyal
    
    
    
    
  331. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-09-17T04:36:41Z

    Few comments:
    
    1)
    The message of patch001 says:
    ----
    When a sequence is synchronized to the subscriber, the page LSN of the
    sequence from the publisher is also captured and stored in
    pg_subscription_rel.srsublsn. This LSN will reflect the state of the
    sequence at the time of synchronization. By comparing the current LSN
    of the sequence on the publisher (via pg_sequence_state()) with the
    stored LSN on the subscriber, users can detect if the sequence has
    advanced and is now out-of-sync. This comparison will help determine
    whether re-synchronization is needed for a given sequence.
    ----
    
    I am unsure if pg_subscription_rel.srsublsn can help diagnose thatseq
    is out-of-sync. The page-lsn can be the same but the sequence-values
    can still be unsynchronized. Same page-lsn does not necessarily mean
    synchronized sequences.
    
    
    patch002:
    2)
    + if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
    + {
    + if (pubform->puballtables && pubform->puballsequences)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("publication \"%s\" is defined as FOR ALL TABLES, ALL SEQUENCES",
    + NameStr(pubform->pubname)),
    + errdetail("Schemas cannot be added to or dropped from FOR ALL
    TABLES, ALL SEQUENCES publications."));
    + else if (pubform->puballtables)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    + NameStr(pubform->pubname)),
    + errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    publications."));
    + else
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("publication \"%s\" is defined as FOR ALL SEQUENCES",
    + NameStr(pubform->pubname)),
    + errdetail("Schemas cannot be added to or dropped from FOR ALL
    SEQUENCES publications."));
    + }
    
    Do you think we can make it as:
    
    if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
    {
      ereport(ERROR,
         errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
         errmsg("Schemas cannot be added to or dropped from publication
    defined for ALL TABLES, ALL SEQUENCES, or both"));
    }
    
    IMO, a generic message such as above is good enough.
    Same is applicable to the next 'Tables or sequences' message.
    
    
    patch003:
    3)
    /*
     * Return whether the subscription currently has any relations.
     *
     * Note: Unlike HasSubscriptionRelations(), this function relies on cached
     * information for subscription relations. Additionally, it should not be
     * invoked outside of apply or tablesync workers, as MySubscription must be
     * initialized first.
     */
    bool
    HasSubscriptionRelationsCached(void)
    {
            /* We need up-to-date subscription tables info here */
            return FetchRelationStates(NULL);
    }
    
    a) The comment mentions old function name HasSubscriptionRelations()
    b) I think this function only worries about tables as we are passing
    has_pending_sequences as NULL.
    
    So does the comment and function name need amendments from relation to table?
    
    
    patch005:
    4)
    + * root partitioned tables. This is not applicable for FOR ALL SEQEUNCES
    + * publication.
    
    a) SEQEUNCES --> SEQUENCES
    
    b) We may say (omit FOR):
     This is not applicable to ALL SEQUENCES publication.
    
    
    5)
     * If getting tables and not_ready is false get all tables, otherwise,
     * only get tables that have not reached READY state.
     * If getting sequences and not_ready is false get all sequences,
     * otherwise, only get sequences that have not reached READY state (i.e. are
     * still in INIT state).
    
    Shall we rephrase to:
    /*
     * If getting tables and not_ready is false, retrieve all tables;
     * otherwise, retrieve only tables that have not reached the READY state.
     *
     * If getting sequences and not_ready is false, retrieve all sequences;
     * otherwise, retrieve only sequences that are still in the INIT state
     * (i.e., have not reached the READY state).
     */
    
    Reviewing further..
    
    thanks
    Shveta
    
    
    
    
  332. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2025-09-17T13:38:30Z

    On Mon, 15 Sept 2025 at 14:36, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 8 Sept 2025 at 12:05, Chao Li <li.evan.chao@gmail.com> wrote:
    > >
    > >
    > >
    > > On Sep 8, 2025, at 14:00, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > >
    > >
    > > 1 - 0001
    > > ```
    > > diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql
    > > index 2c220b60749..c8adddbfa31 100644
    > > --- a/src/test/regress/sql/sequence.sql
    > > +++ b/src/test/regress/sql/sequence.sql
    > > @@ -414,6 +414,6 @@ SELECT nextval('test_seq1');
    > > SELECT nextval('test_seq1');
    > >
    > > -- pg_get_sequence_data
    > > -SELECT * FROM pg_get_sequence_data('test_seq1');
    > > +SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    > >
    > > DROP SEQUENCE test_seq1;
    > > ```
    > >
    > > As it shows log_cnt now, after calling pg_get_sequence_data(), I suggest add 8 nextval(), so that sequence goes to 11, and log_cnt should become to 22.
    > >
    > >
    > > Could you please explain the reason you’d like this to be done?
    > >
    > >
    > > Because log_cnt is newly exposed, we want to verify its value in the test. When I first time ran the test code, I saw initial value of log_cnt was 32, then I thought log_cnt might get decreased if I ran nextval() again, but it didn’t. Only after I ran 10 (cache size) more nextval(), log_cnt got decreased by 10 to 22. The test code is a place for people to look for expected behavior. So I think adding more nextval() to verify and show the change of log_cnt is helpful.
    >
    > This is addressed in the attached patch, also rebased the patch
    > because of recent commits.
    
    Hi Vignesh,
    
    Here are some more review comments:
    
    For patch 0006:
    
    1. Spelling mistake in:
    + appendStringInfo(combined_error_detail, "Insufficent permission for
    sequence(s): (%s).",
    + insuffperm_seqs->data);
    
    Insufficent -> Insufficient
    
    2. Spelling mistake in:
    + ereport(LOG,
    + errmsg("logical replication sequence synchronization for
    subscription \"%s\" - batch #%d = %d attempted, %d succeeded, %d
    skipped, %d mismatched, %d insufficient pemission, %d missing, ",
    +    MySubscription->name, (current_index /
    MAX_SEQUENCES_SYNC_PER_BATCH) + 1, batch_size,
    +    batch_succeeded_count, batch_skipped_count,
    batch_mismatched_count, batch_insuffperm_count,
    +    batch_size - (batch_succeeded_count + batch_skipped_count +
    batch_mismatched_count + batch_insuffperm_count)));
    
    pemission -> permission
    
    3. I ran the ALTER SUBSCRIPTION .. REFRESH PUBLICATION command and
    DROP SEQUENCE command and got a warning for "leaked hash_seq_search
    scan". Is it expected?
    
    2025-09-17 19:06:48.663 IST [2995060] LOG:  logical replication
    sequence synchronization worker for subscription "sub1" has started
    2025-09-17 19:06:48.677 IST [2995060] LOG:  logical replication
    sequence synchronization for subscription "sub1" - total
    unsynchronized: 0
    2025-09-17 19:06:48.677 IST [2995060] WARNING:  leaked hash_seq_search
    scan for hash table 0x62b0a61d3450
    2025-09-17 19:06:48.677 IST [2995060] LOG:  logical replication
    sequence synchronization worker for subscription "sub1" has finished
    
    Steps to reproduce:
    1. create publication for ALL SEQUENCES and create a subscription for
    the publication on another node.
    2. create sequence s1 both on publisher and subscriber.
    3. Attach gdb on a psql terminal and add breakpoint at "line of
    function call to AddSubscriptionRelState" inside function
    AlterSubscription_refresh and run ALTER PUBLICATION .. REFRESH
    PUBLICATION command on psql terminal
    4. DROP sequence s1 on another terminal(for subscriber)
    5. Continue the gdb
    We will get the above warning.
    
    Thanks,
    Shlok Kyal
    
    
    
    
  333. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-17T15:54:25Z

    On Wed, 17 Sept 2025 at 10:06, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > Few comments:
    >
    > 1)
    > The message of patch001 says:
    > ----
    > When a sequence is synchronized to the subscriber, the page LSN of the
    > sequence from the publisher is also captured and stored in
    > pg_subscription_rel.srsublsn. This LSN will reflect the state of the
    > sequence at the time of synchronization. By comparing the current LSN
    > of the sequence on the publisher (via pg_sequence_state()) with the
    > stored LSN on the subscriber, users can detect if the sequence has
    > advanced and is now out-of-sync. This comparison will help determine
    > whether re-synchronization is needed for a given sequence.
    > ----
    >
    > I am unsure if pg_subscription_rel.srsublsn can help diagnose thatseq
    > is out-of-sync. The page-lsn can be the same but the sequence-values
    > can still be unsynchronized. Same page-lsn does not necessarily mean
    > synchronized sequences.
    
    Currently we don't WAL log every sequence change, it happens once in
    32 changes. I felt this was fine. Do you want anything additionally to
    be included?
    
    > patch002:
    > 2)
    > + if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
    > + {
    > + if (pubform->puballtables && pubform->puballsequences)
    > + ereport(ERROR,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("publication \"%s\" is defined as FOR ALL TABLES, ALL SEQUENCES",
    > + NameStr(pubform->pubname)),
    > + errdetail("Schemas cannot be added to or dropped from FOR ALL
    > TABLES, ALL SEQUENCES publications."));
    > + else if (pubform->puballtables)
    > + ereport(ERROR,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    > + NameStr(pubform->pubname)),
    > + errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    > publications."));
    > + else
    > + ereport(ERROR,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("publication \"%s\" is defined as FOR ALL SEQUENCES",
    > + NameStr(pubform->pubname)),
    > + errdetail("Schemas cannot be added to or dropped from FOR ALL
    > SEQUENCES publications."));
    > + }
    >
    > Do you think we can make it as:
    >
    > if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
    > {
    >   ereport(ERROR,
    >      errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    >      errmsg("Schemas cannot be added to or dropped from publication
    > defined for ALL TABLES, ALL SEQUENCES, or both"));
    > }
    >
    > IMO, a generic message such as above is good enough.
    > Same is applicable to the next 'Tables or sequences' message.
    
    I'm ok with the generic error message, modified accordingly.
    
    > patch003:
    > 3)
    > /*
    >  * Return whether the subscription currently has any relations.
    >  *
    >  * Note: Unlike HasSubscriptionRelations(), this function relies on cached
    >  * information for subscription relations. Additionally, it should not be
    >  * invoked outside of apply or tablesync workers, as MySubscription must be
    >  * initialized first.
    >  */
    > bool
    > HasSubscriptionRelationsCached(void)
    > {
    >         /* We need up-to-date subscription tables info here */
    >         return FetchRelationStates(NULL);
    > }
    >
    > a) The comment mentions old function name HasSubscriptionRelations()
    > b) I think this function only worries about tables as we are passing
    > has_pending_sequences as NULL.
    >
    > So does the comment and function name need amendments from relation to table?
    
    Modified
    
    > patch005:
    > 4)
    > + * root partitioned tables. This is not applicable for FOR ALL SEQEUNCES
    > + * publication.
    >
    > a) SEQEUNCES --> SEQUENCES
    >
    > b) We may say (omit FOR):
    >  This is not applicable to ALL SEQUENCES publication.
    
    Modified
    
    > 5)
    >  * If getting tables and not_ready is false get all tables, otherwise,
    >  * only get tables that have not reached READY state.
    >  * If getting sequences and not_ready is false get all sequences,
    >  * otherwise, only get sequences that have not reached READY state (i.e. are
    >  * still in INIT state).
    >
    > Shall we rephrase to:
    > /*
    >  * If getting tables and not_ready is false, retrieve all tables;
    >  * otherwise, retrieve only tables that have not reached the READY state.
    >  *
    >  * If getting sequences and not_ready is false, retrieve all sequences;
    >  * otherwise, retrieve only sequences that are still in the INIT state
    >  * (i.e., have not reached the READY state).
    >  */
    
    Modified
    
    Thanks for the comments. The attached patches has the changes for the
    same. Also Shlok's comments from [1] have also been addressed.
    
    [1] - https://www.postgresql.org/message-id/CANhcyEUHS%2BkjS0AQhVEgLF0Yf0dEZkxczEriN4su5mQqZnxU8g%40mail.gmail.com
    
    Regards,
    Vignesh
    
  334. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-18T10:31:09Z

    On Wed, 17 Sept 2025 at 19:08, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    >
    > On Mon, 15 Sept 2025 at 14:36, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Mon, 8 Sept 2025 at 12:05, Chao Li <li.evan.chao@gmail.com> wrote:
    > > >
    > > >
    > > >
    > > > On Sep 8, 2025, at 14:00, vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > >
    > > >
    > > > 1 - 0001
    > > > ```
    > > > diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql
    > > > index 2c220b60749..c8adddbfa31 100644
    > > > --- a/src/test/regress/sql/sequence.sql
    > > > +++ b/src/test/regress/sql/sequence.sql
    > > > @@ -414,6 +414,6 @@ SELECT nextval('test_seq1');
    > > > SELECT nextval('test_seq1');
    > > >
    > > > -- pg_get_sequence_data
    > > > -SELECT * FROM pg_get_sequence_data('test_seq1');
    > > > +SELECT last_value, is_called, log_cnt, page_lsn <= pg_current_wal_lsn() as lsn FROM pg_get_sequence_data('test_seq1');
    > > >
    > > > DROP SEQUENCE test_seq1;
    > > > ```
    > > >
    > > > As it shows log_cnt now, after calling pg_get_sequence_data(), I suggest add 8 nextval(), so that sequence goes to 11, and log_cnt should become to 22.
    > > >
    > > >
    > > > Could you please explain the reason you’d like this to be done?
    > > >
    > > >
    > > > Because log_cnt is newly exposed, we want to verify its value in the test. When I first time ran the test code, I saw initial value of log_cnt was 32, then I thought log_cnt might get decreased if I ran nextval() again, but it didn’t. Only after I ran 10 (cache size) more nextval(), log_cnt got decreased by 10 to 22. The test code is a place for people to look for expected behavior. So I think adding more nextval() to verify and show the change of log_cnt is helpful.
    > >
    > > This is addressed in the attached patch, also rebased the patch
    > > because of recent commits.
    >
    > Hi Vignesh,
    >
    > Here are some more review comments:
    >
    > For patch 0006:
    >
    > 1. Spelling mistake in:
    > + appendStringInfo(combined_error_detail, "Insufficent permission for
    > sequence(s): (%s).",
    > + insuffperm_seqs->data);
    >
    > Insufficent -> Insufficient
    >
    > 2. Spelling mistake in:
    > + ereport(LOG,
    > + errmsg("logical replication sequence synchronization for
    > subscription \"%s\" - batch #%d = %d attempted, %d succeeded, %d
    > skipped, %d mismatched, %d insufficient pemission, %d missing, ",
    > +    MySubscription->name, (current_index /
    > MAX_SEQUENCES_SYNC_PER_BATCH) + 1, batch_size,
    > +    batch_succeeded_count, batch_skipped_count,
    > batch_mismatched_count, batch_insuffperm_count,
    > +    batch_size - (batch_succeeded_count + batch_skipped_count +
    > batch_mismatched_count + batch_insuffperm_count)));
    >
    > pemission -> permission
    >
    > 3. I ran the ALTER SUBSCRIPTION .. REFRESH PUBLICATION command and
    > DROP SEQUENCE command and got a warning for "leaked hash_seq_search
    > scan". Is it expected?
    >
    > 2025-09-17 19:06:48.663 IST [2995060] LOG:  logical replication
    > sequence synchronization worker for subscription "sub1" has started
    > 2025-09-17 19:06:48.677 IST [2995060] LOG:  logical replication
    > sequence synchronization for subscription "sub1" - total
    > unsynchronized: 0
    > 2025-09-17 19:06:48.677 IST [2995060] WARNING:  leaked hash_seq_search
    > scan for hash table 0x62b0a61d3450
    > 2025-09-17 19:06:48.677 IST [2995060] LOG:  logical replication
    > sequence synchronization worker for subscription "sub1" has finished
    >
    > Steps to reproduce:
    > 1. create publication for ALL SEQUENCES and create a subscription for
    > the publication on another node.
    > 2. create sequence s1 both on publisher and subscriber.
    > 3. Attach gdb on a psql terminal and add breakpoint at "line of
    > function call to AddSubscriptionRelState" inside function
    > AlterSubscription_refresh and run ALTER PUBLICATION .. REFRESH
    > PUBLICATION command on psql terminal
    > 4. DROP sequence s1 on another terminal(for subscriber)
    > 5. Continue the gdb
    > We will get the above warning.
    
    Thanks for the comments, these are handled in the attached patch.
    
    Regards,
    Vignesh
    
  335. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-09-22T06:33:19Z

    On Thu, Sep 18, 2025 at 4:07 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > Thanks for the comments, these are handled in the attached patch.
    >
    
    Please find a few comments:
    
    
    patch005:
    1)
    GetSubscriptionRelations:
    + /* Skip sequences if they were not requested */
    + if (!get_sequences && (relkind == RELKIND_SEQUENCE))
    + continue;
    +
    + /* Skip tables if they were not requested */
    + if (!get_tables && (relkind != RELKIND_SEQUENCE))
    + continue;
    
    The use of negated conditions makes the logic harder to follow,
    especially in the second if block.
    
    Can we write it as:
       bool is_sequence = (relkind == RELKIND_SEQUENCE);
    
       /* Skip if the relation type is not requested */
       if ((get_tables && is_sequence) ||
           (get_sequences && !is_sequence))
           continue;
    
    Or at-least:
    /* Skip sequences if they were not requested */
    if (get_tables && (relkind == RELKIND_SEQUENCE))
      continue;
    
    /* Skip tables if they were not requested */
    if (get_sequences && (relkind != RELKIND_SEQUENCE))
      continue;
    
    2)
    
    AlterSubscription_refresh_seq:
    
    + UpdateSubscriptionRelState(sub->oid, relid, SUBREL_STATE_DATASYNC,
    +    InvalidXLogRecPtr, false);
    
    Now it seems we are setting SUBREL_STATE_DATASYNC state as well for
    sequences. Earlier it was INIT only.
    
    So we need correction at 2 places:
    a)
    Comment atop GetSubscriptionRelations() which mentions :
     * If getting sequences and not_ready is false, retrieve all sequences;
     * otherwise, retrieve only sequences that are still in the INIT state
     * (i.e., have not reached the READY state).
    
    We shall change it to that have not reached the READY state.
    
    b)
    patch 006's commit message says:
    This patch introduces sequence synchronization:
    Sequences have 2 states:
       - INIT (needs synchronizing)
       - READY (is already synchronized)
    
    We shall mention the third state as well.
    
    
    3)
    There is some optimization in fetch_relation_list() in patch006. I
    think it should be in patch005 itself where we have4 added new logic
    to fetch sequeneces and relkind in patch005.
    Or do we need those for patch006 specifically?
    
    
    patch006:
    4)
    sequencesync.c:
    
    + * Sequences to be synchronized by the sequencesync worker will
    + * be added to pg_subscription_rel in INIT state when one of the following
    + * commands is executed:
    + * CREATE SUBSCRIPTION
    + * ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    + * ALTER SUBSCRIPTION ... REFRESH PUBLICATION SEQUENCES
    
    I think this comment needs change. 'REFRESH PUBLICATION SEQUENCES' is
    not doing that anymore.
    
    5)
     * So the state progression is always just: INIT -> READY.
    I see even SUBREL_STATE_DATASYNC being set now by
    AlterSubscription_refresh_seq()
    
    thanks
    Shveta
    
    
    
    
  336. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-09-22T10:03:03Z

    6)
    I tried to test the patch. When sequences are more than the
    batch-size, but not enough to make a complete batch of max size, I get
    this error:
    
    LOG:  logical replication sequence synchronization for subscription
    "sub1" - total unsynchronized: 118
    LOG:  logical replication sequence synchronization for subscription
    "sub1" - batch #1 = 100 attempted, 100 succeeded, 0 skipped, 0
    mismatched, 0 insufficient pemission, 0 missing,
    WARNING:  leaked hash_seq_search scan for hash table 0x5fcc78ff8f90
    ERROR:  no hash_seq_search scan for hash table "Logical replication
    sequence sync worker sequences"
    LOG:  background worker "logical replication sequencesync worker" (PID
    137165) exited with exit code 1
    
    This is on creating 118 sequences. It can be easily reproduced by
    reducing bath-size (MAX_SEQUENCES_SYNC_PER_BATCH) to say 5 and having
    6 sequences in total. It seems we break out of the loop of creating a
    batch only if batch_size >= MAX_SEQUENCES_SYNC_PER_BATCH.  When we try
    to access hash_seq_search() more than the entries present, it gives
    the above error.
    
    thanks
    Shveta
    
    
    
    
  337. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-23T13:09:27Z

    On Mon, 22 Sept 2025 at 12:03, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Thu, Sep 18, 2025 at 4:07 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > Thanks for the comments, these are handled in the attached patch.
    > >
    >
    > Please find a few comments:
    >
    >
    > patch005:
    > 1)
    > GetSubscriptionRelations:
    > + /* Skip sequences if they were not requested */
    > + if (!get_sequences && (relkind == RELKIND_SEQUENCE))
    > + continue;
    > +
    > + /* Skip tables if they were not requested */
    > + if (!get_tables && (relkind != RELKIND_SEQUENCE))
    > + continue;
    >
    > The use of negated conditions makes the logic harder to follow,
    > especially in the second if block.
    >
    > Can we write it as:
    >    bool is_sequence = (relkind == RELKIND_SEQUENCE);
    >
    >    /* Skip if the relation type is not requested */
    >    if ((get_tables && is_sequence) ||
    >        (get_sequences && !is_sequence))
    >        continue;
    >
    > Or at-least:
    > /* Skip sequences if they were not requested */
    > if (get_tables && (relkind == RELKIND_SEQUENCE))
    >   continue;
    >
    > /* Skip tables if they were not requested */
    > if (get_sequences && (relkind != RELKIND_SEQUENCE))
    >   continue;
    
    I felt this would not work. Say we want both sequences and tables,
    won't it skip the sequence this way from:
    if (get_tables && (relkind == RELKIND_SEQUENCE))
      continue;
    
    Rest of the comments were fixed, also the comment from [1] is fixed in
    the attached patch.
    [1] - https://www.postgresql.org/message-id/CAJpy0uAdD9XtZCE34BJhbvncMgfmMuTS0ZXLP1P=g+wpRC8vqQ@mail.gmail.com
    
    Regards,
    Vignesh
    
  338. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-09-25T06:53:40Z

    On Tue, Sep 23, 2025 at 6:39 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 22 Sept 2025 at 12:03, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Thu, Sep 18, 2025 at 4:07 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > Thanks for the comments, these are handled in the attached patch.
    > > >
    > >
    > > Please find a few comments:
    > >
    > >
    > > patch005:
    > > 1)
    > > GetSubscriptionRelations:
    > > + /* Skip sequences if they were not requested */
    > > + if (!get_sequences && (relkind == RELKIND_SEQUENCE))
    > > + continue;
    > > +
    > > + /* Skip tables if they were not requested */
    > > + if (!get_tables && (relkind != RELKIND_SEQUENCE))
    > > + continue;
    > >
    > > The use of negated conditions makes the logic harder to follow,
    > > especially in the second if block.
    > >
    > > Can we write it as:
    > >    bool is_sequence = (relkind == RELKIND_SEQUENCE);
    > >
    > >    /* Skip if the relation type is not requested */
    > >    if ((get_tables && is_sequence) ||
    > >        (get_sequences && !is_sequence))
    > >        continue;
    > >
    > > Or at-least:
    > > /* Skip sequences if they were not requested */
    > > if (get_tables && (relkind == RELKIND_SEQUENCE))
    > >   continue;
    > >
    > > /* Skip tables if they were not requested */
    > > if (get_sequences && (relkind != RELKIND_SEQUENCE))
    > >   continue;
    >
    > I felt this would not work. Say we want both sequences and tables,
    > won't it skip the sequence this way from:
    > if (get_tables && (relkind == RELKIND_SEQUENCE))
    >   continue;
    >
    
    Okay, I see your point. In that case, could we reverse the conditions
    instead? That seems like the more obvious choice in terms of
    readability :
    if ((relkind == RELKIND_SEQUENCE && !get_sequences))
        continue;
    
    if ((relkind != RELKIND_SEQUENCE && !get_tables))
        continue;
    
    For second if-block, more understandable conditions will be:
    (relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE)
    && !get_tables
    
    But here we will have to check relkind twice, so I leave the decision to you.
    
    ~~
    
    Few comments on latest patch:
    
    LogicalRepSyncSequences():
    1)
    + seq_entry = hash_search(sequences_to_copy, &key,
    + HASH_ENTER, &found);
    + Assert(seq_entry != NULL);
    
    Since we are using HASH_ENTER, it will be good to add Assert(!found) as well.
    
    2)
    + sequences_to_copy = hash_create("Logical replication sequence sync
    worker sequences",
    + 256, &ctl, HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
    +
    
    The name of the hash-table looks odd. Shall it simply be 'Logical
    replication sequences'. 'Logical Replication' is good enough to give
    an indication that these are sequences being synchronized by seq-sync
    worker.
    
    ~~
    
    copy_sequences():
    3)
    + if (batch_size >= MAX_SEQUENCES_SYNC_PER_BATCH ||
    + (current_index + batch_size == total_seqs))
    + break;
    
    In the first condition, I think a better comparison will be equality
    one (batch_size == MAX_SEQUENCES_SYNC_PER_BATCH). We are not letting
    batch_size go beyond MAX_SEQUENCES_SYNC_PER_BATCH.
    
    4)
    + if (batch_size == 0)
    + {
    + CommitTransactionCommand();
    + break;
    + }
    
    I could not think of a scenario when this will be hit. The outer loop
    condition has 'while (current_index < total_seqs)', so batch_size has
    to be something. Even if we skip some entries due to
    remote_seq_queried being set to true already, that should not make
    batch_size as 0 as the entries with remote_seq_queried=true are
    already accounted for in current_index. Or am I missing something
    here?
    
    ~~
    
    sequencesync_list_invalidate_cb():
    5)
    
    + /* invalidate all entries */
    + hash_seq_init(&status, sequences_to_copy);
    + while ((entry = (LogicalRepSequenceInfo *) hash_seq_search(&status)) != NULL)
    + entry->entry_valid = false;
    
    Can you please elaborate when this case can be hit? I see such logic
    in all such invalidation functions registered with
    CacheRegisterRelcacheCallback(), but could not find any relevant
    comment.
    
    ~~
    
    Reviewing further.
    
    thanks
    Shveta
    
    
    
    
  339. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-26T07:25:27Z

    On Thu, 25 Sept 2025 at 12:23, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > sequencesync_list_invalidate_cb():
    > 5)
    >
    > + /* invalidate all entries */
    > + hash_seq_init(&status, sequences_to_copy);
    > + while ((entry = (LogicalRepSequenceInfo *) hash_seq_search(&status)) != NULL)
    > + entry->entry_valid = false;
    >
    > Can you please elaborate when this case can be hit? I see such logic
    > in all such invalidation functions registered with
    > CacheRegisterRelcacheCallback(), but could not find any relevant
    > comment.
    
    I noticed this could happen in cases like:
    create publication for all tables;
    alter publication on many relations;
    
    but there might be more apart from this
    
    Rest of the comments were addressed.
    The attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  340. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-09-29T04:28:49Z

    On Fri, Sep 26, 2025 at 12:55 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 25 Sept 2025 at 12:23, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > sequencesync_list_invalidate_cb():
    > > 5)
    > >
    > > + /* invalidate all entries */
    > > + hash_seq_init(&status, sequences_to_copy);
    > > + while ((entry = (LogicalRepSequenceInfo *) hash_seq_search(&status)) != NULL)
    > > + entry->entry_valid = false;
    > >
    > > Can you please elaborate when this case can be hit? I see such logic
    > > in all such invalidation functions registered with
    > > CacheRegisterRelcacheCallback(), but could not find any relevant
    > > comment.
    >
    > I noticed this could happen in cases like:
    > create publication for all tables;
    > alter publication on many relations;
    >
    > but there might be more apart from this
    >
    
    Okay. I will review more here.
    
    > Rest of the comments were addressed.
    > The attached patch has the changes for the same.
    >
    
    Thanks.
    
    I found a race condition between the apply worker and the sequence
    sync worker, where a sequence might be deleted from
    pg_subscription_rel and fail to be re-added when it should be.
    
    Steps:
    
    1)
    The publisher and subscriber both have two sequences: seq1 and seq2.
    
    2)
    A REFRESH PUBLICATION SEQUENCES command is executed on the subscriber.
    Before the sequencesync worker on the subscriber can locate the
    corresponding sequence on the publisher, the sequence gets dropped on
    the publisher. In other words, the sequence is removed from the
    publisher before walrcv_exec() is called in copy_sequences().
    
    3)
    Before the sequencesync worker on the subscriber can drop the sequence
    locally, it is recreated on the publisher. Then, a second REFRESH
    PUBLICATION SEQUENCES command is executed on the subscriber. (i.e.,
    before RemoveSubscriptionRel() is reached in copy_sequences(), the
    sequence is already recreated on the publisher and a new refresh
    command is issued on the subscriber.)
    
    4)
    During this second REFRESH PUBLICATION SEQUENCES, the sequence is
    found to already exist in pg_subscription_rel, so it is not re-added.
    However, concurrently, the sequencesync worker from the first refresh
    proceeds and drops the sequence from the subscriber.
    
    As a result, the sequence ends up being removed from
    pg_subscription_rel, even though it should have remained after both
    REFRESH PUBLICATION SEQUENCES commands.
    
    thanks
    Shveta
    
    
    
    
  341. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-09-30T16:25:34Z

    On Mon, 29 Sept 2025 at 09:59, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Fri, Sep 26, 2025 at 12:55 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Thu, 25 Sept 2025 at 12:23, shveta malik <shveta.malik@gmail.com> wrote:
    > > >
    > > > sequencesync_list_invalidate_cb():
    > > > 5)
    > > >
    > > > + /* invalidate all entries */
    > > > + hash_seq_init(&status, sequences_to_copy);
    > > > + while ((entry = (LogicalRepSequenceInfo *) hash_seq_search(&status)) != NULL)
    > > > + entry->entry_valid = false;
    > > >
    > > > Can you please elaborate when this case can be hit? I see such logic
    > > > in all such invalidation functions registered with
    > > > CacheRegisterRelcacheCallback(), but could not find any relevant
    > > > comment.
    > >
    > > I noticed this could happen in cases like:
    > > create publication for all tables;
    > > alter publication on many relations;
    > >
    > > but there might be more apart from this
    > >
    >
    > Okay. I will review more here.
    >
    > > Rest of the comments were addressed.
    > > The attached patch has the changes for the same.
    > >
    >
    > Thanks.
    >
    > I found a race condition between the apply worker and the sequence
    > sync worker, where a sequence might be deleted from
    > pg_subscription_rel and fail to be re-added when it should be.
    >
    > Steps:
    >
    > 1)
    > The publisher and subscriber both have two sequences: seq1 and seq2.
    >
    > 2)
    > A REFRESH PUBLICATION SEQUENCES command is executed on the subscriber.
    > Before the sequencesync worker on the subscriber can locate the
    > corresponding sequence on the publisher, the sequence gets dropped on
    > the publisher. In other words, the sequence is removed from the
    > publisher before walrcv_exec() is called in copy_sequences().
    >
    > 3)
    > Before the sequencesync worker on the subscriber can drop the sequence
    > locally, it is recreated on the publisher. Then, a second REFRESH
    > PUBLICATION SEQUENCES command is executed on the subscriber. (i.e.,
    > before RemoveSubscriptionRel() is reached in copy_sequences(), the
    > sequence is already recreated on the publisher and a new refresh
    > command is issued on the subscriber.)
    >
    > 4)
    > During this second REFRESH PUBLICATION SEQUENCES, the sequence is
    > found to already exist in pg_subscription_rel, so it is not re-added.
    > However, concurrently, the sequencesync worker from the first refresh
    > proceeds and drops the sequence from the subscriber.
    >
    > As a result, the sequence ends up being removed from
    > pg_subscription_rel, even though it should have remained after both
    > REFRESH PUBLICATION SEQUENCES commands.
    
    I've resolved it by modifying the sequence sync worker to no longer
    remove sequences from pg_subscription_rel, aligning its behavior with
    that of the tablesync worker. This change ensures consistency and also
    addresses the reported problem. The attached patch includes the
    necessary modifications.
    
    Regards,
    Vignesh
    
  342. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-04T15:54:32Z

    On Tue, Sep 30, 2025 at 9:55 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    
    In the 0001 patch, pg_get_sequence_data() exposes two new fields
    log_cnt and page_lsn. I see that the later subscriber-side patch uses
    both, the first one in SetSequence(). It is not clear from the
    comments or the commit message of 0001 why it is necessary to use
    log_cnt when setting the sequence. Can you explain what the problem
    will be if we don't use log_cnt during sequence sync?
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  343. Re: Logical Replication of sequences

    Michael Paquier <michael@paquier.xyz> — 2025-10-05T02:23:54Z

    On Sat, Oct 04, 2025 at 09:24:32PM +0530, Amit Kapila wrote:
    > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > both, the first one in SetSequence(). It is not clear from the
    > comments or the commit message of 0001 why it is necessary to use
    > log_cnt when setting the sequence. Can you explain what the problem
    > will be if we don't use log_cnt during sequence sync?
    
    FWIW, I have argued two times at least that it should never be
    necessary to expose log_cnt in the sequence meta-data: this is just a
    counter to decide when a WAL record of a sequence should be generated.
    
    If you are copying some sequence data over the wire on a new node in a
    logical shape where WAL is independent, this counter is irrelevant:
    you can just reset it.  Please see also a83a944e9fdd.
    --
    Michael
    
  344. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-06T06:11:31Z

    On Sun, Oct 5, 2025 at 7:54 AM Michael Paquier <michael@paquier.xyz> wrote:
    >
    > On Sat, Oct 04, 2025 at 09:24:32PM +0530, Amit Kapila wrote:
    > > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > > both, the first one in SetSequence(). It is not clear from the
    > > comments or the commit message of 0001 why it is necessary to use
    > > log_cnt when setting the sequence. Can you explain what the problem
    > > will be if we don't use log_cnt during sequence sync?
    >
    > FWIW, I have argued two times at least that it should never be
    > necessary to expose log_cnt in the sequence meta-data: this is just a
    > counter to decide when a WAL record of a sequence should be generated.
    >
    > If you are copying some sequence data over the wire on a new node in a
    > logical shape where WAL is independent, this counter is irrelevant:
    > you can just reset it.  Please see also a83a944e9fdd.
    >
    
    Agreed and I think we have the same behaviour after upgrade.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  345. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-06T06:19:52Z

    On Sun, 5 Oct 2025 at 07:54, Michael Paquier <michael@paquier.xyz> wrote:
    >
    > On Sat, Oct 04, 2025 at 09:24:32PM +0530, Amit Kapila wrote:
    > > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > > both, the first one in SetSequence(). It is not clear from the
    > > comments or the commit message of 0001 why it is necessary to use
    > > log_cnt when setting the sequence. Can you explain what the problem
    > > will be if we don't use log_cnt during sequence sync?
    >
    > FWIW, I have argued two times at least that it should never be
    > necessary to expose log_cnt in the sequence meta-data: this is just a
    > counter to decide when a WAL record of a sequence should be generated.
    
    Thanks, I have verified that the log_cnt value is not retained after an upgrade:
    create sequence s1;
    select nextval('s1');
    select nextval('s1');
    
    postgres=# select * from s1;
    last_value | log_cnt | is_called
    ------------+---------+-----------
              2 |      31 | t
    (1 row)
    
    After upgrade:
    postgres=# select * from s1;
    last_value | log_cnt | is_called
    ------------+---------+-----------
              2 |       0 | t
    (1 row)
    
    Since the log_cnt value is not preserved across upgrades, copying it
    would have no effect. I’ll remove log_cnt from pg_get_sequence_data
    and post an updated version of the patch.
    
    Regards,
    Vignesh
    
    
    
    
  346. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-06T06:37:03Z

    On Sat, 4 Oct 2025 at 21:24, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Sep 30, 2025 at 9:55 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    >
    > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > both, the first one in SetSequence(). It is not clear from the
    > comments or the commit message of 0001 why it is necessary to use
    > log_cnt when setting the sequence. Can you explain what the problem
    > will be if we don't use log_cnt during sequence sync?
    
    I thought to keep the log_cnt value the same value as the publisher.
    I have verified from the upgrade that we don't retain the log_cnt
    value after upgrade, even if we copy log_cnt, the value will not be
    retained. The attached
    v20251006-0001-Enhance-pg_get_sequence_data-function.patch has the
    changes to remove log_cnt.
    
    Regards,
    Vignesh
    
  347. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-06T11:03:42Z

    On Mon, 6 Oct 2025 at 12:07, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Sat, 4 Oct 2025 at 21:24, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Tue, Sep 30, 2025 at 9:55 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > >
    > > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > > both, the first one in SetSequence(). It is not clear from the
    > > comments or the commit message of 0001 why it is necessary to use
    > > log_cnt when setting the sequence. Can you explain what the problem
    > > will be if we don't use log_cnt during sequence sync?
    >
    > I thought to keep the log_cnt value the same value as the publisher.
    > I have verified from the upgrade that we don't retain the log_cnt
    > value after upgrade, even if we copy log_cnt, the value will not be
    > retained. The attached
    > v20251006-0001-Enhance-pg_get_sequence_data-function.patch has the
    > changes to remove log_cnt.
    
    Here is the rebased remaining patches.
    
    Regards,
    Vignesh
    
  348. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-07T05:23:14Z

    On Mon, Oct 6, 2025 at 4:33 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > Here is the rebased remaining patches.
    >
    
    Thank You for the patches, please find a few comment on 001:
    
    1)
    Shall we have 'pg_publication_sequences' created in the first patch
    itself to help verify which all sequences are added to ALL SEQ
    publications? Currently it is in 4th patch.
    
    2)
    postgres=# create publication pub1 for all sequences WITH(publish='insert');
    ERROR:  publication parameters are not supported for publications
    defined as FOR ALL SEQUENCES
    
    postgres=# alter publication pub1 add table tab1;
    ERROR:  Tables or sequences cannot be added to or dropped from
    publication defined FOR ALL TABLES, ALL SEQUENCES, or both
    
    a) First msg has 'as', while second does not. Shall we make both the
    same? I think we can get rid of 'as'.
    b) Shouldn't the error msg start with lower case (second one)?
    
    
    3)
    + * Process all_objects_list to set all_tables/all_sequences.
    
    can we please replace 'all_tables/all_sequences' with 'all_tables
    and/or all_sequences'
    
    4)
    +/*
    + * Publication types supported by FOR ALL ...
    + */
    +typedef enum PublicationAllObjType
    
    Should it be:
    'Types of objects supported by FOR ALL publications'
    
    5)
    +-- Specifying both ALL TABLES and ALL SEQUENCES along with WITH
    clause should throw a warning
    +SET client_min_messages = 'NOTICE';
    +CREATE PUBLICATION regress_pub_for_allsequences_alltables_withcaluse
    FOR ALL SEQUENCES, ALL TABLES WITH (publish = 'insert');
    +NOTICE:  publication parameters are not applicable to sequence
    synchronization and will be ignored
    
    Comment can be changed to say it will emit/raise a NOTICE (instead of warning).
    
    6)
    commit msg:
    --
    Note: This patch currently supports only the "ALL SEQUENCES" clause.
    Handling of clauses such as "FOR SEQUENCE" and "FOR SEQUENCES IN SCHEMA"
    will be addressed in a subsequent patch.
    --
    
    This seems misleading, as we are not planning the "FOR SEQUENCE" in
    the current set of patches, maybe we can rephrase it a bit.
    
    thanks
    Shveta
    
    
    
    
  349. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-07T06:39:01Z

    On Tue, Oct 7, 2025 at 10:53 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > 2)
    > postgres=# create publication pub1 for all sequences WITH(publish='insert');
    > ERROR:  publication parameters are not supported for publications
    > defined as FOR ALL SEQUENCES
    >
    > postgres=# alter publication pub1 add table tab1;
    > ERROR:  Tables or sequences cannot be added to or dropped from
    > publication defined FOR ALL TABLES, ALL SEQUENCES, or both
    >
    > a) First msg has 'as', while second does not. Shall we make both the
    > same? I think we can get rid of 'as'.
    > b) Shouldn't the error msg start with lower case (second one)?
    >
    
    The (b) is related to following change:
    
    +  if (tables && (pubform->puballtables || pubform->puballsequences))
        ereport(ERROR,
    -        (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    -         errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    -            NameStr(pubform->pubname)),
    -         errdetail("Tables cannot be added to or dropped from FOR ALL
    TABLES publications.")));
    +        errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    +        errmsg("Tables or sequences cannot be added to or dropped
    from publication defined FOR ALL TABLES, ALL SEQUENCES, or both"));
    }
    
    I see a bigger problem where we made errdetail as errmsg. Here, we are
    trying to combine the message FOR ALL TABLES and FOR ALL SEQUENCES
    which caused this change/confusion. It is better to keep them separate
    to avoid confusion. The similar problem exists for following message:
    - if (schemaidlist && pubform->puballtables)
    + if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
      ereport(ERROR,
    - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    - errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    - NameStr(pubform->pubname)),
    - errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    publications.")));
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("Schemas cannot be added to or dropped from publication
    defined FOR ALL TABLES, ALL SEQUENCES, or both"));
    
    If we fix both of these then we don't need to do anything for point (a).
    
    Few other comments:
    =================
    1. Is there a reason not to change just the footers part in
    describeOneTableDetails()?
    2. I think we can move create_publication.sgml and
    pg_publication_sequences related changes to 0001 from doc patch.
    3. Atop is_publishable_class(), we mention it has all the checks as
    check_publication_add_relation but the sequence check is different. Is
    it because check_publication_add_relation() is not called FOR ALL
    SEQUENCES? If so, I have modified a few comments in the attached
    related to that.
    4.
    @@ -878,13 +885,35 @@ CreatePublication(ParseState *pstate,
    CreatePublicationStmt *stmt)
        &publish_via_partition_root_given,
        &publish_via_partition_root,
        &publish_generated_columns_given,
    -   &publish_generated_columns);
    +   &publish_generated_columns,
    +   def_pub_action);
    +
    + if (stmt->for_all_sequences &&
    + (publish_given || publish_via_partition_root_given ||
    + publish_generated_columns_given))
    + {
    + /*
    + * WITH clause parameters are not applicable when creating a FOR ALL
    + * SEQUENCES publication. If the publication includes tables as well,
    + * issue a notice.
    + */
    + if (!stmt->for_all_tables)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("publication parameters are not supported for publications
    defined as FOR ALL SEQUENCES"));
    +
    + ereport(NOTICE,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("publication parameters are not applicable to sequence
    synchronization and will be ignored"));
    + }
    
    This change looks a bit ad hoc to me. I think it would be better to
    handle this inside parse_publication_options(). The function can take
    the third parameter as for_all_sequences and then use that to give
    error when any options are present.
    
    -- 
    With Regards,
    Amit Kapila.
    
  350. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-07T08:51:13Z

    On Mon, Oct 6, 2025 at 4:33 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 6 Oct 2025 at 12:07, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Sat, 4 Oct 2025 at 21:24, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Tue, Sep 30, 2025 at 9:55 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > >
    > > > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > > > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > > > both, the first one in SetSequence(). It is not clear from the
    > > > comments or the commit message of 0001 why it is necessary to use
    > > > log_cnt when setting the sequence. Can you explain what the problem
    > > > will be if we don't use log_cnt during sequence sync?
    > >
    > > I thought to keep the log_cnt value the same value as the publisher.
    > > I have verified from the upgrade that we don't retain the log_cnt
    > > value after upgrade, even if we copy log_cnt, the value will not be
    > > retained. The attached
    > > v20251006-0001-Enhance-pg_get_sequence_data-function.patch has the
    > > changes to remove log_cnt.
    >
    > Here is the rebased remaining patches.
    
    While testing the patches with different combinations to make
    publications, I do not understand why we don't support ALL SEQUENCE
    with some table option, or is it future pending work.
    
    postgres[1390699]=# CREATE PUBLICATION pub FOR ALL SEQUENCES, table test;
    ERROR:  42601: syntax error at or near "table"
    LINE 1: CREATE PUBLICATION pub FOR ALL SEQUENCES, table test;
    LOCATION:  scanner_yyerror, scan.l:1236
    
    
    postgres[1390699]=# CREATE PUBLICATION pub FOR table test, ALL SEQUENCES;
    ERROR:  42601: syntax error at or near "all"
    LINE 1: CREATE PUBLICATION pub FOR table test, all sequences;
    
    I am doing more review/test from a usability perspective, but thought
    of asking this, while I am reviewing further.
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  351. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-07T10:21:41Z

    On Tue, Oct 7, 2025 at 2:21 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Mon, Oct 6, 2025 at 4:33 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Mon, 6 Oct 2025 at 12:07, vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Sat, 4 Oct 2025 at 21:24, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > > > On Tue, Sep 30, 2025 at 9:55 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > >
    > > > >
    > > > > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > > > > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > > > > both, the first one in SetSequence(). It is not clear from the
    > > > > comments or the commit message of 0001 why it is necessary to use
    > > > > log_cnt when setting the sequence. Can you explain what the problem
    > > > > will be if we don't use log_cnt during sequence sync?
    > > >
    > > > I thought to keep the log_cnt value the same value as the publisher.
    > > > I have verified from the upgrade that we don't retain the log_cnt
    > > > value after upgrade, even if we copy log_cnt, the value will not be
    > > > retained. The attached
    > > > v20251006-0001-Enhance-pg_get_sequence_data-function.patch has the
    > > > changes to remove log_cnt.
    > >
    > > Here is the rebased remaining patches.
    >
    > While testing the patches with different combinations to make
    > publications, I do not understand why we don't support ALL SEQUENCE
    > with some table option, or is it future pending work.
    >
    
    Yes, it is left for future similar to the cases like FOR SEQUENCE s1
    or FOR SEQUENCES IN SCHEMA. The key idea was to first support the
    cases required for upgrade and we can later extend the feature after
    some user feedback or separate discussion with -hackers to see what
    others think. Does that sound reasonable to you?
    
    >
    > I am doing more review/test from a usability perspective, but thought
    > of asking this, while I am reviewing further.
    >
    
    Thanks.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  352. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-07T11:21:48Z

    On Tue, 7 Oct 2025 at 12:09, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Oct 7, 2025 at 10:53 AM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > 2)
    > > postgres=# create publication pub1 for all sequences WITH(publish='insert');
    > > ERROR:  publication parameters are not supported for publications
    > > defined as FOR ALL SEQUENCES
    > >
    > > postgres=# alter publication pub1 add table tab1;
    > > ERROR:  Tables or sequences cannot be added to or dropped from
    > > publication defined FOR ALL TABLES, ALL SEQUENCES, or both
    > >
    > > a) First msg has 'as', while second does not. Shall we make both the
    > > same? I think we can get rid of 'as'.
    > > b) Shouldn't the error msg start with lower case (second one)?
    > >
    >
    > The (b) is related to following change:
    >
    > +  if (tables && (pubform->puballtables || pubform->puballsequences))
    > ereport(ERROR,
    > -        (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > -         errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    > -            NameStr(pubform->pubname)),
    > -         errdetail("Tables cannot be added to or dropped from FOR ALL
    > TABLES publications.")));
    > +        errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > +        errmsg("Tables or sequences cannot be added to or dropped
    > from publication defined FOR ALL TABLES, ALL SEQUENCES, or both"));
    > }
    >
    > I see a bigger problem where we made errdetail as errmsg. Here, we are
    > trying to combine the message FOR ALL TABLES and FOR ALL SEQUENCES
    > which caused this change/confusion. It is better to keep them separate
    > to avoid confusion. The similar problem exists for following message:
    > - if (schemaidlist && pubform->puballtables)
    > + if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
    >   ereport(ERROR,
    > - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > - errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    > - NameStr(pubform->pubname)),
    > - errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    > publications.")));
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("Schemas cannot be added to or dropped from publication
    > defined FOR ALL TABLES, ALL SEQUENCES, or both"));
    
    Modified to keep it as separate error messages.
    
    > If we fix both of these then we don't need to do anything for point (a).
    
    Agreed
    
    > Few other comments:
    > =================
    > 1. Is there a reason not to change just the footers part in
    > describeOneTableDetails()?
    
    I tried the approach to keep it as a footer and it simplifies the code
    further. Update the patch accordingly.
    
    > 2. I think we can move create_publication.sgml and
    > pg_publication_sequences related changes to 0001 from doc patch.
    
    Modified
    
    > 3. Atop is_publishable_class(), we mention it has all the checks as
    > check_publication_add_relation but the sequence check is different. Is
    > it because check_publication_add_relation() is not called FOR ALL
    > SEQUENCES? If so, I have modified a few comments in the attached
    > related to that.
    
    Updated
    
    > 4.
    > @@ -878,13 +885,35 @@ CreatePublication(ParseState *pstate,
    > CreatePublicationStmt *stmt)
    >     &publish_via_partition_root_given,
    >     &publish_via_partition_root,
    >     &publish_generated_columns_given,
    > -   &publish_generated_columns);
    > +   &publish_generated_columns,
    > +   def_pub_action);
    > +
    > + if (stmt->for_all_sequences &&
    > + (publish_given || publish_via_partition_root_given ||
    > + publish_generated_columns_given))
    > + {
    > + /*
    > + * WITH clause parameters are not applicable when creating a FOR ALL
    > + * SEQUENCES publication. If the publication includes tables as well,
    > + * issue a notice.
    > + */
    > + if (!stmt->for_all_tables)
    > + ereport(ERROR,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("publication parameters are not supported for publications
    > defined as FOR ALL SEQUENCES"));
    > +
    > + ereport(NOTICE,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("publication parameters are not applicable to sequence
    > synchronization and will be ignored"));
    > + }
    >
    > This change looks a bit ad hoc to me. I think it would be better to
    > handle this inside parse_publication_options(). The function can take
    > the third parameter as for_all_sequences and then use that to give
    > error when any options are present.
    
    Modified
    
    Thanks for the comments, the attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  353. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-07T11:25:49Z

    On Tue, Oct 7, 2025 at 3:51 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Oct 7, 2025 at 2:21 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Mon, Oct 6, 2025 at 4:33 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Mon, 6 Oct 2025 at 12:07, vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > On Sat, 4 Oct 2025 at 21:24, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > >
    > > > > > On Tue, Sep 30, 2025 at 9:55 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > >
    > > > > >
    > > > > > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > > > > > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > > > > > both, the first one in SetSequence(). It is not clear from the
    > > > > > comments or the commit message of 0001 why it is necessary to use
    > > > > > log_cnt when setting the sequence. Can you explain what the problem
    > > > > > will be if we don't use log_cnt during sequence sync?
    > > > >
    > > > > I thought to keep the log_cnt value the same value as the publisher.
    > > > > I have verified from the upgrade that we don't retain the log_cnt
    > > > > value after upgrade, even if we copy log_cnt, the value will not be
    > > > > retained. The attached
    > > > > v20251006-0001-Enhance-pg_get_sequence_data-function.patch has the
    > > > > changes to remove log_cnt.
    > > >
    > > > Here is the rebased remaining patches.
    > >
    > > While testing the patches with different combinations to make
    > > publications, I do not understand why we don't support ALL SEQUENCE
    > > with some table option, or is it future pending work.
    > >
    >
    > Yes, it is left for future similar to the cases like FOR SEQUENCE s1
    > or FOR SEQUENCES IN SCHEMA. The key idea was to first support the
    > cases required for upgrade and we can later extend the feature after
    > some user feedback or separate discussion with -hackers to see what
    > others think. Does that sound reasonable to you?
    
    Yeah that's correct, I think the main use case for sequence
    synchronization is upgrade and it makes sense to use ALL TABLES/ALL
    SEQUENCES for upgrade.  However, if a user is using selective tables
    for upgrade for now they might not be able to use ALL SEQUENCE and
    that should be fine as we are going to provide add on functionality.
    
    I have one more question: while testing the sequence sync, I found
    this behavior is documented as well[1], but what's the reasoning
    behind it?  Why REFRESH PUBLICATION will synchronize only newly added
    sequences and need to use REFRESH PUBLICATION SEQUENCES to
    re-synchronize all sequences.
    
    I mean what will be the use case where users just want to synchronize
    the newly added sequences and not others?
    
    [1]
    +     <para>
    +      use <link linkend="sql-altersubscription-params-refresh-publication">
    +      <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</command></link>
    +      to synchronize only newly added sequences.
    +     </para>
    +    </listitem>
    +    <listitem>
    +     <para>
    +      use <link
    linkend="sql-altersubscription-params-refresh-publication-sequences">
    +      <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    SEQUENCES</command></link>
    +      to re-synchronize all sequences.
    +     </para>
    
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  354. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-07T11:26:12Z

    On Tue, 7 Oct 2025 at 10:53, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Mon, Oct 6, 2025 at 4:33 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > >
    > > Here is the rebased remaining patches.
    > >
    >
    > Thank You for the patches, please find a few comment on 001:
    >
    > 1)
    > Shall we have 'pg_publication_sequences' created in the first patch
    > itself to help verify which all sequences are added to ALL SEQ
    > publications? Currently it is in 4th patch.
    
    Moved it to 0001 patch
    
    > 2)
    > postgres=# create publication pub1 for all sequences WITH(publish='insert');
    > ERROR:  publication parameters are not supported for publications
    > defined as FOR ALL SEQUENCES
    >
    > postgres=# alter publication pub1 add table tab1;
    > ERROR:  Tables or sequences cannot be added to or dropped from
    > publication defined FOR ALL TABLES, ALL SEQUENCES, or both
    >
    > a) First msg has 'as', while second does not. Shall we make both the
    > same? I think we can get rid of 'as'.
    
    The second error message is changed now based on another comment, so
    both of them will have as now.
    
    > b) Shouldn't the error msg start with lower case (second one)?
    
    Updated
    
    > 3)
    > + * Process all_objects_list to set all_tables/all_sequences.
    >
    > can we please replace 'all_tables/all_sequences' with 'all_tables
    > and/or all_sequences'
    
    Updated
    
    > 4)
    > +/*
    > + * Publication types supported by FOR ALL ...
    > + */
    > +typedef enum PublicationAllObjType
    >
    > Should it be:
    > 'Types of objects supported by FOR ALL publications'
    
    Modified
    
    > 5)
    > +-- Specifying both ALL TABLES and ALL SEQUENCES along with WITH
    > clause should throw a warning
    > +SET client_min_messages = 'NOTICE';
    > +CREATE PUBLICATION regress_pub_for_allsequences_alltables_withcaluse
    > FOR ALL SEQUENCES, ALL TABLES WITH (publish = 'insert');
    > +NOTICE:  publication parameters are not applicable to sequence
    > synchronization and will be ignored
    >
    > Comment can be changed to say it will emit/raise a NOTICE (instead of warning).
    
    Modified
    
    > 6)
    > commit msg:
    > --
    > Note: This patch currently supports only the "ALL SEQUENCES" clause.
    > Handling of clauses such as "FOR SEQUENCE" and "FOR SEQUENCES IN SCHEMA"
    > will be addressed in a subsequent patch.
    > --
    >
    > This seems misleading, as we are not planning the "FOR SEQUENCE" in
    > the current set of patches, maybe we can rephrase it a bit.
    
    Modified
    
    Thanks for the comments, the v20251007 patch attached at [1] has the
    changes for the same.
    
    [1] - https://www.postgresql.org/message-id/CALDaNm3NJBiXpQ3uY8%3DXhSPd6jBn2rTJS6wJZSFo6m2pzW5hqw%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  355. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-07T12:16:04Z

    On Tue, Oct 7, 2025 at 4:56 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Tue, Oct 7, 2025 at 3:51 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Tue, Oct 7, 2025 at 2:21 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > >
    > > > On Mon, Oct 6, 2025 at 4:33 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > On Mon, 6 Oct 2025 at 12:07, vignesh C <vignesh21@gmail.com> wrote:
    > > > > >
    > > > > > On Sat, 4 Oct 2025 at 21:24, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > >
    > > > > > > On Tue, Sep 30, 2025 at 9:55 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > > >
    > > > > > >
    > > > > > > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > > > > > > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > > > > > > both, the first one in SetSequence(). It is not clear from the
    > > > > > > comments or the commit message of 0001 why it is necessary to use
    > > > > > > log_cnt when setting the sequence. Can you explain what the problem
    > > > > > > will be if we don't use log_cnt during sequence sync?
    > > > > >
    > > > > > I thought to keep the log_cnt value the same value as the publisher.
    > > > > > I have verified from the upgrade that we don't retain the log_cnt
    > > > > > value after upgrade, even if we copy log_cnt, the value will not be
    > > > > > retained. The attached
    > > > > > v20251006-0001-Enhance-pg_get_sequence_data-function.patch has the
    > > > > > changes to remove log_cnt.
    > > > >
    > > > > Here is the rebased remaining patches.
    > > >
    > > > While testing the patches with different combinations to make
    > > > publications, I do not understand why we don't support ALL SEQUENCE
    > > > with some table option, or is it future pending work.
    > > >
    > >
    > > Yes, it is left for future similar to the cases like FOR SEQUENCE s1
    > > or FOR SEQUENCES IN SCHEMA. The key idea was to first support the
    > > cases required for upgrade and we can later extend the feature after
    > > some user feedback or separate discussion with -hackers to see what
    > > others think. Does that sound reasonable to you?
    >
    > Yeah that's correct, I think the main use case for sequence
    > synchronization is upgrade and it makes sense to use ALL TABLES/ALL
    > SEQUENCES for upgrade.  However, if a user is using selective tables
    > for upgrade for now they might not be able to use ALL SEQUENCE and
    > that should be fine as we are going to provide add on functionality.
    >
    
    Yes, we can add the additional functionality for selective sequences
    if required but do we have an option to allow upgrade of selective
    tables?
    
    > I have one more question: while testing the sequence sync, I found
    > this behavior is documented as well[1], but what's the reasoning
    > behind it?  Why REFRESH PUBLICATION will synchronize only newly added
    > sequences and need to use REFRESH PUBLICATION SEQUENCES to
    > re-synchronize all sequences.
    >
    
    The idea is that REFRESH PUBLICATION should behave similarly for
    tables and sequences. This means that this command is primarily used
    to add/remove tables/sequences and copy their respective initial
    contents. The new command REFRESH PUBLICATION SEQUENCES is to sync the
    existing sequences, it shouldn't add any new sequences, now, if it is
    too confusing we can discuss having a different syntax for it. In the
    meantime, let's make the 0001 publication-side patch ready for commit.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  356. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-08T03:43:21Z

    On Tue, Oct 7, 2025 at 5:46 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Oct 7, 2025 at 4:56 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Tue, Oct 7, 2025 at 3:51 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Tue, Oct 7, 2025 at 2:21 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > > >
    > > > > On Mon, Oct 6, 2025 at 4:33 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > >
    > > > > > On Mon, 6 Oct 2025 at 12:07, vignesh C <vignesh21@gmail.com> wrote:
    > > > > > >
    > > > > > > On Sat, 4 Oct 2025 at 21:24, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > > >
    > > > > > > > On Tue, Sep 30, 2025 at 9:55 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > > > > > >
    > > > > > > >
    > > > > > > > In the 0001 patch, pg_get_sequence_data() exposes two new fields
    > > > > > > > log_cnt and page_lsn. I see that the later subscriber-side patch uses
    > > > > > > > both, the first one in SetSequence(). It is not clear from the
    > > > > > > > comments or the commit message of 0001 why it is necessary to use
    > > > > > > > log_cnt when setting the sequence. Can you explain what the problem
    > > > > > > > will be if we don't use log_cnt during sequence sync?
    > > > > > >
    > > > > > > I thought to keep the log_cnt value the same value as the publisher.
    > > > > > > I have verified from the upgrade that we don't retain the log_cnt
    > > > > > > value after upgrade, even if we copy log_cnt, the value will not be
    > > > > > > retained. The attached
    > > > > > > v20251006-0001-Enhance-pg_get_sequence_data-function.patch has the
    > > > > > > changes to remove log_cnt.
    > > > > >
    > > > > > Here is the rebased remaining patches.
    > > > >
    > > > > While testing the patches with different combinations to make
    > > > > publications, I do not understand why we don't support ALL SEQUENCE
    > > > > with some table option, or is it future pending work.
    > > > >
    > > >
    > > > Yes, it is left for future similar to the cases like FOR SEQUENCE s1
    > > > or FOR SEQUENCES IN SCHEMA. The key idea was to first support the
    > > > cases required for upgrade and we can later extend the feature after
    > > > some user feedback or separate discussion with -hackers to see what
    > > > others think. Does that sound reasonable to you?
    > >
    > > Yeah that's correct, I think the main use case for sequence
    > > synchronization is upgrade and it makes sense to use ALL TABLES/ALL
    > > SEQUENCES for upgrade.  However, if a user is using selective tables
    > > for upgrade for now they might not be able to use ALL SEQUENCE and
    > > that should be fine as we are going to provide add on functionality.
    > >
    >
    > Yes, we can add the additional functionality for selective sequences
    > if required but do we have an option to allow upgrade of selective
    > tables?
    
    If the user is upgrading using logical replication, then there is an
    option to set up a replication from the current version to the next
    major version and then the user can selectively publish the table
    which is supposed to be streamed to the next major version. right?
    
    > > I have one more question: while testing the sequence sync, I found
    > > this behavior is documented as well[1], but what's the reasoning
    > > behind it?  Why REFRESH PUBLICATION will synchronize only newly added
    > > sequences and need to use REFRESH PUBLICATION SEQUENCES to
    > > re-synchronize all sequences.
    > >
    >
    > The idea is that REFRESH PUBLICATION should behave similarly for
    > tables and sequences. This means that this command is primarily used
    > to add/remove tables/sequences and copy their respective initial
    > contents. The new command REFRESH PUBLICATION SEQUENCES is to sync the
    > existing sequences, it shouldn't add any new sequences, now, if it is
    > too confusing we can discuss having a different syntax for it.
    
    Sure, let's discuss this when we get this patch at the start of the
    commit queue.
    
     In the
    > meantime, let's make the 0001 publication-side patch ready for commit.
    
    Make sense.
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  357. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-08T05:35:54Z

    On Wed, Oct 8, 2025 at 9:13 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Tue, Oct 7, 2025 at 5:46 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > >
    > > Yes, we can add the additional functionality for selective sequences
    > > if required but do we have an option to allow upgrade of selective
    > > tables?
    >
    > If the user is upgrading using logical replication, then there is an
    > option to set up a replication from the current version to the next
    > major version and then the user can selectively publish the table
    > which is supposed to be streamed to the next major version. right?
    >
    
    Yes, that is possible. However, during the upgrade of the publisher
    node, if the user wants to shift the workload to the subscriber then
    ideally she should sync all sequences. But I think there could be
    cases where users may wish to selectively replicate sequences, so we
    can consider such cases as well once the main feature is committed.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  358. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-08T06:37:04Z

    On Tue, Oct 7, 2025 at 4:56 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 7 Oct 2025 at 10:53, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Mon, Oct 6, 2025 at 4:33 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > >
    > > > Here is the rebased remaining patches.
    > > >
    > >
    > > Thank You for the patches, please find a few comment on 001:
    > >
    > > 1)
    > > Shall we have 'pg_publication_sequences' created in the first patch
    > > itself to help verify which all sequences are added to ALL SEQ
    > > publications? Currently it is in 4th patch.
    >
    > Moved it to 0001 patch
    >
    > > 2)
    > > postgres=# create publication pub1 for all sequences WITH(publish='insert');
    > > ERROR:  publication parameters are not supported for publications
    > > defined as FOR ALL SEQUENCES
    > >
    > > postgres=# alter publication pub1 add table tab1;
    > > ERROR:  Tables or sequences cannot be added to or dropped from
    > > publication defined FOR ALL TABLES, ALL SEQUENCES, or both
    > >
    > > a) First msg has 'as', while second does not. Shall we make both the
    > > same? I think we can get rid of 'as'.
    >
    > The second error message is changed now based on another comment, so
    > both of them will have as now.
    >
    > > b) Shouldn't the error msg start with lower case (second one)?
    >
    > Updated
    >
    > > 3)
    > > + * Process all_objects_list to set all_tables/all_sequences.
    > >
    > > can we please replace 'all_tables/all_sequences' with 'all_tables
    > > and/or all_sequences'
    >
    > Updated
    >
    > > 4)
    > > +/*
    > > + * Publication types supported by FOR ALL ...
    > > + */
    > > +typedef enum PublicationAllObjType
    > >
    > > Should it be:
    > > 'Types of objects supported by FOR ALL publications'
    >
    > Modified
    >
    > > 5)
    > > +-- Specifying both ALL TABLES and ALL SEQUENCES along with WITH
    > > clause should throw a warning
    > > +SET client_min_messages = 'NOTICE';
    > > +CREATE PUBLICATION regress_pub_for_allsequences_alltables_withcaluse
    > > FOR ALL SEQUENCES, ALL TABLES WITH (publish = 'insert');
    > > +NOTICE:  publication parameters are not applicable to sequence
    > > synchronization and will be ignored
    > >
    > > Comment can be changed to say it will emit/raise a NOTICE (instead of warning).
    >
    > Modified
    >
    > > 6)
    > > commit msg:
    > > --
    > > Note: This patch currently supports only the "ALL SEQUENCES" clause.
    > > Handling of clauses such as "FOR SEQUENCE" and "FOR SEQUENCES IN SCHEMA"
    > > will be addressed in a subsequent patch.
    > > --
    > >
    > > This seems misleading, as we are not planning the "FOR SEQUENCE" in
    > > the current set of patches, maybe we can rephrase it a bit.
    >
    > Modified
    >
    > Thanks for the comments, the v20251007 patch attached at [1] has the
    > changes for the same.
    >
    
    Thanks for making the changes.  Just one trivial comment:
    
    We can have 'applicable to' instead of 'applicable for' in all these places:
    
    a)
    + /* Publication actions are not applicable for sequence-only publications */
    
    b)
    +      publishing tables. This clause is not applicable for sequences. The
    
    c)
    + errmsg("publication parameters are not applicable for publications
    defined as FOR ALL SEQUENCES"));
    
    
    thanks
    Shveta
    
    
    
    
  359. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-08T09:10:21Z

    On Tue, Oct 7, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > Thanks for the comments, the attached patch has the changes for the same.
    >
    
     parse_publication_options(ParseState *pstate,
        List *options,
    +   bool allsequences,
    +   bool alltables,
        bool *publish_given,
        PublicationActions *pubactions,
        bool *publish_via_partition_root_given,
        bool *publish_via_partition_root,
        bool *publish_generated_columns_given,
    -   char *publish_generated_columns)
    +   char *publish_generated_columns,
    +   bool def_pub_action)
    {
    …
    +
    + if (allsequences &&
    + (*publish_given || *publish_via_partition_root_given ||
    + *publish_generated_columns_given))
    + {
    + if (!alltables)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("publication parameters are not applicable for publications
    defined as FOR ALL SEQUENCES"));
    
    I think we can let users specify publication parameters even for
    sequence_only publication as well. Because users could then later add
    tables to it by Alter Publication .. Add .. The notice should be
    sufficient and also then it would bebetter to give it outside this
    function as that could be extended in future when we would allow a mix
    of sequence and table publications.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  360. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-08T09:11:27Z

    On Tue, Oct 7, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 7 Oct 2025 at 12:09, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    
    I think the patch is mostly LGTM, I have 2 suggestions, see if you
    think this is useful.
    
    1.
    postgres[1390699]=# CREATE PUBLICATION pub FOR ALL SEQUENCES, ALL
    TABLES WITH (publish = insert);
    NOTICE:  55000: publication parameters are not applicable to sequence
    synchronization and will be ignored
    LOCATION:  CreatePublication, publicationcmds.c:905
    
    IMHO this notice seems confusing, from this it appears that (publish =
    insert) is ignored completely, but actually it is is not ignored for
    table, should we explicitely say that it will be ignored only for
    sequences.  Something like below?
    
    "publication parameters are not applicable to sequence synchronization
    so it will be used only for tables and will be ignored for sequence
    synchronization"
    or
    "publication parameters are not applicable to sequence synchronization
    so it will be ignored for the sequence synchronization"
    
    2.
    + if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
    + {
    + if (pubform->puballtables && pubform->puballsequences)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("publication \"%s\" is defined as FOR ALL TABLES, ALL SEQUENCES",
    +    NameStr(pubform->pubname)),
    + errdetail("Schemas cannot be added to or dropped from FOR ALL
    TABLES, ALL SEQUENCES publications."));
    + else if (pubform->puballtables)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    +    NameStr(pubform->pubname)),
    + errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    publications."));
    + else
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("publication \"%s\" is defined as FOR ALL SEQUENCES",
    +    NameStr(pubform->pubname)),
    + errdetail("Schemas cannot be added to or dropped from FOR ALL
    SEQUENCES publications."));
    + }
    
    Can't we make this a single generic error message instead of
    duplicating for each combination?  Something like
    
    errmsg("publication \"%s\" is defined as FOR ALL TABLES or ALL SEQUENCES",
       NameStr(pubform->pubname)),
    errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    or ALL SEQUENCES publications."));
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  361. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-08T09:45:33Z

    On Wed, Oct 8, 2025 at 2:41 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Tue, Oct 7, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Tue, 7 Oct 2025 at 12:09, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    >
    > I think the patch is mostly LGTM, I have 2 suggestions, see if you
    > think this is useful.
    >
    > 1.
    > postgres[1390699]=# CREATE PUBLICATION pub FOR ALL SEQUENCES, ALL
    > TABLES WITH (publish = insert);
    > NOTICE:  55000: publication parameters are not applicable to sequence
    > synchronization and will be ignored
    > LOCATION:  CreatePublication, publicationcmds.c:905
    >
    > IMHO this notice seems confusing, from this it appears that (publish =
    > insert) is ignored completely, but actually it is is not ignored for
    > table, should we explicitely say that it will be ignored only for
    > sequences.  Something like below?
    >
    > "publication parameters are not applicable to sequence synchronization
    > so it will be used only for tables and will be ignored for sequence
    > synchronization"
    > or
    > "publication parameters are not applicable to sequence synchronization
    > so it will be ignored for the sequence synchronization"
    >
    
    How about a slightly shorter form like: 'publication parameters are
    not applicable to sequence synchronization and will be ignored for
    sequences'?
    
    > 2.
    > + if (schemaidlist && (pubform->puballtables || pubform->puballsequences))
    > + {
    > + if (pubform->puballtables && pubform->puballsequences)
    > + ereport(ERROR,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("publication \"%s\" is defined as FOR ALL TABLES, ALL SEQUENCES",
    > +    NameStr(pubform->pubname)),
    > + errdetail("Schemas cannot be added to or dropped from FOR ALL
    > TABLES, ALL SEQUENCES publications."));
    > + else if (pubform->puballtables)
    > + ereport(ERROR,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    > +    NameStr(pubform->pubname)),
    > + errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    > publications."));
    > + else
    > + ereport(ERROR,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > + errmsg("publication \"%s\" is defined as FOR ALL SEQUENCES",
    > +    NameStr(pubform->pubname)),
    > + errdetail("Schemas cannot be added to or dropped from FOR ALL
    > SEQUENCES publications."));
    > + }
    >
    > Can't we make this a single generic error message instead of
    > duplicating for each combination?  Something like
    >
    > errmsg("publication \"%s\" is defined as FOR ALL TABLES or ALL SEQUENCES",
    >    NameStr(pubform->pubname)),
    > errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    > or ALL SEQUENCES publications."));
    >
    
    Yeah,  we can do that but Note that these messages are for the
    existing publication and we are aware of its publicized contents, so
    we can give clear messages to users. Why make it ambiguous?
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  362. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-08T10:08:18Z

    On Wed, 8 Oct 2025 at 3:15 PM, Amit Kapila <amit.kapila16@gmail.com> wrote:
    
    > On Wed, Oct 8, 2025 at 2:41 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Tue, Oct 7, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Tue, 7 Oct 2025 at 12:09, Amit Kapila <amit.kapila16@gmail.com>
    > wrote:
    > > > >
    > >
    > > I think the patch is mostly LGTM, I have 2 suggestions, see if you
    > > think this is useful.
    > >
    > > 1.
    > > postgres[1390699]=# CREATE PUBLICATION pub FOR ALL SEQUENCES, ALL
    > > TABLES WITH (publish = insert);
    > > NOTICE:  55000: publication parameters are not applicable to sequence
    > > synchronization and will be ignored
    > > LOCATION:  CreatePublication, publicationcmds.c:905
    > >
    > > IMHO this notice seems confusing, from this it appears that (publish =
    > > insert) is ignored completely, but actually it is is not ignored for
    > > table, should we explicitely say that it will be ignored only for
    > > sequences.  Something like below?
    > >
    > > "publication parameters are not applicable to sequence synchronization
    > > so it will be used only for tables and will be ignored for sequence
    > > synchronization"
    > > or
    > > "publication parameters are not applicable to sequence synchronization
    > > so it will be ignored for the sequence synchronization"
    > >
    >
    > How about a slightly shorter form like: 'publication parameters are
    > not applicable to sequence synchronization and will be ignored for
    > sequences'?
    
    
    
    Works for me.
    
    
    > 2.
    > > + if (schemaidlist && (pubform->puballtables ||
    > pubform->puballsequences))
    > > + {
    > > + if (pubform->puballtables && pubform->puballsequences)
    > > + ereport(ERROR,
    > > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > > + errmsg("publication \"%s\" is defined as FOR ALL TABLES, ALL
    > SEQUENCES",
    > > +    NameStr(pubform->pubname)),
    > > + errdetail("Schemas cannot be added to or dropped from FOR ALL
    > > TABLES, ALL SEQUENCES publications."));
    > > + else if (pubform->puballtables)
    > > + ereport(ERROR,
    > > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > > + errmsg("publication \"%s\" is defined as FOR ALL TABLES",
    > > +    NameStr(pubform->pubname)),
    > > + errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    > > publications."));
    > > + else
    > > + ereport(ERROR,
    > > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    > > + errmsg("publication \"%s\" is defined as FOR ALL SEQUENCES",
    > > +    NameStr(pubform->pubname)),
    > > + errdetail("Schemas cannot be added to or dropped from FOR ALL
    > > SEQUENCES publications."));
    > > + }
    > >
    > > Can't we make this a single generic error message instead of
    > > duplicating for each combination?  Something like
    > >
    > > errmsg("publication \"%s\" is defined as FOR ALL TABLES or ALL
    > SEQUENCES",
    > >    NameStr(pubform->pubname)),
    > > errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES
    > > or ALL SEQUENCES publications."));
    > >
    >
    > Yeah,  we can do that but Note that these messages are for the
    > existing publication and we are aware of its publicized contents, so
    > we can give clear messages to users. Why make it ambiguous?
    
    
    Hmm, yeah that makes sense.
    
    
    —
    Dilip
    
  363. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-08T10:19:57Z

    On Wed, 8 Oct 2025 at 15:38, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Wed, 8 Oct 2025 at 3:15 PM, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >>
    >> On Wed, Oct 8, 2025 at 2:41 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >> >
    >> > On Tue, Oct 7, 2025 at 4:52 PM vignesh C <vignesh21@gmail.com> wrote:
    >> > >
    >> > > On Tue, 7 Oct 2025 at 12:09, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >> > > >
    >> >
    >> > I think the patch is mostly LGTM, I have 2 suggestions, see if you
    >> > think this is useful.
    >> >
    >> > 1.
    >> > postgres[1390699]=# CREATE PUBLICATION pub FOR ALL SEQUENCES, ALL
    >> > TABLES WITH (publish = insert);
    >> > NOTICE:  55000: publication parameters are not applicable to sequence
    >> > synchronization and will be ignored
    >> > LOCATION:  CreatePublication, publicationcmds.c:905
    >> >
    >> > IMHO this notice seems confusing, from this it appears that (publish =
    >> > insert) is ignored completely, but actually it is is not ignored for
    >> > table, should we explicitely say that it will be ignored only for
    >> > sequences.  Something like below?
    >> >
    >> > "publication parameters are not applicable to sequence synchronization
    >> > so it will be used only for tables and will be ignored for sequence
    >> > synchronization"
    >> > or
    >> > "publication parameters are not applicable to sequence synchronization
    >> > so it will be ignored for the sequence synchronization"
    >> >
    >>
    >> How about a slightly shorter form like: 'publication parameters are
    >> not applicable to sequence synchronization and will be ignored for
    >> sequences'?
    >
    > Works for me.
    
    Thanks for the comments, here is an updated version with a fix to handle this.
    
    Regards,
    Vignesh
    
  364. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-08T12:01:40Z

    On Wed, Oct 8, 2025 at 3:50 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > Thanks for the comments, here is an updated version with a fix to handle this.
    >
    
    Thanks. The patch looks good to me.
    
    thanks
    Shveta
    
    
    
    
  365. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-09T04:44:32Z

    On Wed, Oct 8, 2025 at 9:13 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Tue, Oct 7, 2025 at 5:46 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    >
    > > > I have one more question: while testing the sequence sync, I found
    > > > this behavior is documented as well[1], but what's the reasoning
    > > > behind it?  Why REFRESH PUBLICATION will synchronize only newly added
    > > > sequences and need to use REFRESH PUBLICATION SEQUENCES to
    > > > re-synchronize all sequences.
    > > >
    > >
    > > The idea is that REFRESH PUBLICATION should behave similarly for
    > > tables and sequences. This means that this command is primarily used
    > > to add/remove tables/sequences and copy their respective initial
    > > contents. The new command REFRESH PUBLICATION SEQUENCES is to sync the
    > > existing sequences, it shouldn't add any new sequences, now, if it is
    > > too confusing we can discuss having a different syntax for it.
    >
    > Sure, let's discuss this when we get this patch at the start of the
    > commit queue.
    >
    
    I have pushed the publications related patch. Now, we can discuss this
    command. I think confusion arises from the fact that both commands use
    REFRESH. So, how about for the second case (sync/copy all existing
    sequences), we use a different command, some ideas that come to my
    mind are:
    
    Alter Subscription sub1 REPLICATE Publication Sequences;
    Alter Subscription sub1 RESYNC Publication Sequences;
    Alter Subscription sub1 SYNC Publication Sequences;
    Alter Subscription sub1 MERGE Publication Sequences;
    
    Among these, the first three require a new keyword to be introduced. I
    prefer to use existing keyword if possible. Any ideas?
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  366. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-10-09T04:55:10Z

    Dear Amit, Dilip,
    
    > I have pushed the publications related patch. Now, we can discuss this
    > command. I think confusion arises from the fact that both commands use
    > REFRESH. So, how about for the second case (sync/copy all existing
    > sequences), we use a different command, some ideas that come to my
    > mind are:
    > 
    > Alter Subscription sub1 REPLICATE Publication Sequences;
    > Alter Subscription sub1 RESYNC Publication Sequences;
    > Alter Subscription sub1 SYNC Publication Sequences;
    > Alter Subscription sub1 MERGE Publication Sequences;
    > 
    > Among these, the first three require a new keyword to be introduced. I
    > prefer to use existing keyword if possible. Any ideas?
    
    I checked kwlist.h and below might also be used. Thought?
    
    - COPY
    - UPDATE
    - OVERRIDING
    - REPLACE
    - REASSIGN
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
  367. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-09T05:51:25Z

    Hi,
    
    I saw a sequence replication patch was committed recently [1], so I
    was looking at the diffs. Below are a couple of observations:
    
    //////////
    
    1.
    The following message seems overly long:
    errmsg("publication parameters are not applicable to sequence
    synchronization and will be ignored for sequences"));
    
    I saw the message was already discussed here [2], but at that time, it
    was not shortened much.
    
    How about something shorter? Some examples.
    errmsg("publication parameters will be ignored for sequences"));
    errmsg("publication parameters will be ignored for sequence replication"));
    
    ======
    
    2.
    +-- Specifying WITH clause in an ALL SEQUENCES publication will emit a NOTICE.
    +SET client_min_messages = 'NOTICE';
    +CREATE PUBLICATION regress_pub_for_allsequences_alltables_withclause
    FOR ALL SEQUENCES, ALL TABLES WITH (publish = 'insert');
    +CREATE PUBLICATION regress_pub_for_allsequences_withclause FOR ALL
    SEQUENCES WITH (publish_generated_columns = 'stored');
    +RESET client_min_messages;
    
    Why not also test WITH('publish_via_partition_root')?
    
    ======
    [1] https://github.com/postgres/postgres/commit/96b37849734673e7c82fb86c4f0a46a28f500ac8
    [2] https://www.postgresql.org/message-id/CAA4eK1L3SdsMFB6KZ6qEU05wUDtoKS%2BOsvo9UoGP--qVz2PBrg%40mail.gmail.com
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  368. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-09T05:57:17Z

    On Thu, Oct 9, 2025 at 10:14 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Wed, Oct 8, 2025 at 9:13 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Tue, Oct 7, 2025 at 5:46 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > >
    > > > > I have one more question: while testing the sequence sync, I found
    > > > > this behavior is documented as well[1], but what's the reasoning
    > > > > behind it?  Why REFRESH PUBLICATION will synchronize only newly added
    > > > > sequences and need to use REFRESH PUBLICATION SEQUENCES to
    > > > > re-synchronize all sequences.
    > > > >
    > > >
    > > > The idea is that REFRESH PUBLICATION should behave similarly for
    > > > tables and sequences. This means that this command is primarily used
    > > > to add/remove tables/sequences and copy their respective initial
    > > > contents. The new command REFRESH PUBLICATION SEQUENCES is to sync the
    > > > existing sequences, it shouldn't add any new sequences, now, if it is
    > > > too confusing we can discuss having a different syntax for it.
    > >
    > > Sure, let's discuss this when we get this patch at the start of the
    > > commit queue.
    > >
    >
    > I have pushed the publications related patch. Now, we can discuss this
    > command. I think confusion arises from the fact that both commands use
    > REFRESH.
    
    Right
    
     So, how about for the second case (sync/copy all existing
    > sequences), we use a different command, some ideas that come to my
    > mind are:
    >
    > Alter Subscription sub1 REPLICATE Publication Sequences;
    > Alter Subscription sub1 RESYNC Publication Sequences;
    > Alter Subscription sub1 SYNC Publication Sequences;
    > Alter Subscription sub1 MERGE Publication Sequences;
    >
    > Among these, the first three require a new keyword to be introduced. I
    > prefer to use existing keyword if possible. Any ideas?
    
    I would have preferred "Alter Subscription sub1 SYNC Publication
    Sequences" but if your preference is to use existing keywords then
    IMHO "MERGE Publication Sequences" or "UPDATE Publication Sequences"
    are also good options.
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  369. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-09T06:02:18Z

    On Thu, Oct 9, 2025 at 11:27 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Thu, Oct 9, 2025 at 10:14 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Wed, Oct 8, 2025 at 9:13 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > >
    > > > On Tue, Oct 7, 2025 at 5:46 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > >
    > > > > > I have one more question: while testing the sequence sync, I found
    > > > > > this behavior is documented as well[1], but what's the reasoning
    > > > > > behind it?  Why REFRESH PUBLICATION will synchronize only newly added
    > > > > > sequences and need to use REFRESH PUBLICATION SEQUENCES to
    > > > > > re-synchronize all sequences.
    > > > > >
    > > > >
    > > > > The idea is that REFRESH PUBLICATION should behave similarly for
    > > > > tables and sequences. This means that this command is primarily used
    > > > > to add/remove tables/sequences and copy their respective initial
    > > > > contents. The new command REFRESH PUBLICATION SEQUENCES is to sync the
    > > > > existing sequences, it shouldn't add any new sequences, now, if it is
    > > > > too confusing we can discuss having a different syntax for it.
    > > >
    > > > Sure, let's discuss this when we get this patch at the start of the
    > > > commit queue.
    > > >
    > >
    > > I have pushed the publications related patch. Now, we can discuss this
    > > command. I think confusion arises from the fact that both commands use
    > > REFRESH.
    >
    > Right
    >
    >  So, how about for the second case (sync/copy all existing
    > > sequences), we use a different command, some ideas that come to my
    > > mind are:
    > >
    > > Alter Subscription sub1 REPLICATE Publication Sequences;
    > > Alter Subscription sub1 RESYNC Publication Sequences;
    > > Alter Subscription sub1 SYNC Publication Sequences;
    > > Alter Subscription sub1 MERGE Publication Sequences;
    > >
    > > Among these, the first three require a new keyword to be introduced. I
    > > prefer to use existing keyword if possible. Any ideas?
    >
    > I would have preferred "Alter Subscription sub1 SYNC Publication
    > Sequences" but if your preference is to use existing keywords then
    > IMHO "MERGE Publication Sequences" or "UPDATE Publication Sequences"
    > are also good options.
    >
    
    I would prefer "COPY Publication Sequences" or "UPDATE Publication
    Sequences" among the given options. We have a precedence for copy
    (copy_data) in publication command parameters, so, COPY could be a
    better option.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  370. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-09T06:07:45Z

    On Thu, Oct 9, 2025 at 11:21 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > I saw a sequence replication patch was committed recently [1], so I
    > was looking at the diffs. Below are a couple of observations:
    >
    > //////////
    >
    > 1.
    > The following message seems overly long:
    > errmsg("publication parameters are not applicable to sequence
    > synchronization and will be ignored for sequences"));
    >
    > I saw the message was already discussed here [2], but at that time, it
    > was not shortened much.
    >
    > How about something shorter? Some examples.
    > errmsg("publication parameters will be ignored for sequences"));
    > errmsg("publication parameters will be ignored for sequence replication"));
    >
    
    I thought about these alternatives but left in favor of clarity with a
    longer message. However, I am fine to change if others also think so.
    Let's wait and see if others have an opinion on this point.
    
    > ======
    >
    > 2.
    > +-- Specifying WITH clause in an ALL SEQUENCES publication will emit a NOTICE.
    > +SET client_min_messages = 'NOTICE';
    > +CREATE PUBLICATION regress_pub_for_allsequences_alltables_withclause
    > FOR ALL SEQUENCES, ALL TABLES WITH (publish = 'insert');
    > +CREATE PUBLICATION regress_pub_for_allsequences_withclause FOR ALL
    > SEQUENCES WITH (publish_generated_columns = 'stored');
    > +RESET client_min_messages;
    >
    > Why not also test WITH('publish_via_partition_root')?
    >
    
    It is not required to write a test with all the options, the current
    set chosen seems sufficient.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  371. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-09T06:32:20Z

    On Thu, Oct 9, 2025 at 11:32 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Oct 9, 2025 at 11:27 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Thu, Oct 9, 2025 at 10:14 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Wed, Oct 8, 2025 at 9:13 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > > >
    > > > > On Tue, Oct 7, 2025 at 5:46 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > >
    > > > >
    > > > > > > I have one more question: while testing the sequence sync, I found
    > > > > > > this behavior is documented as well[1], but what's the reasoning
    > > > > > > behind it?  Why REFRESH PUBLICATION will synchronize only newly added
    > > > > > > sequences and need to use REFRESH PUBLICATION SEQUENCES to
    > > > > > > re-synchronize all sequences.
    > > > > > >
    > > > > >
    > > > > > The idea is that REFRESH PUBLICATION should behave similarly for
    > > > > > tables and sequences. This means that this command is primarily used
    > > > > > to add/remove tables/sequences and copy their respective initial
    > > > > > contents. The new command REFRESH PUBLICATION SEQUENCES is to sync the
    > > > > > existing sequences, it shouldn't add any new sequences, now, if it is
    > > > > > too confusing we can discuss having a different syntax for it.
    > > > >
    > > > > Sure, let's discuss this when we get this patch at the start of the
    > > > > commit queue.
    > > > >
    > > >
    > > > I have pushed the publications related patch. Now, we can discuss this
    > > > command. I think confusion arises from the fact that both commands use
    > > > REFRESH.
    > >
    > > Right
    > >
    > >  So, how about for the second case (sync/copy all existing
    > > > sequences), we use a different command, some ideas that come to my
    > > > mind are:
    > > >
    > > > Alter Subscription sub1 REPLICATE Publication Sequences;
    > > > Alter Subscription sub1 RESYNC Publication Sequences;
    > > > Alter Subscription sub1 SYNC Publication Sequences;
    > > > Alter Subscription sub1 MERGE Publication Sequences;
    > > >
    > > > Among these, the first three require a new keyword to be introduced. I
    > > > prefer to use existing keyword if possible. Any ideas?
    > >
    > > I would have preferred "Alter Subscription sub1 SYNC Publication
    > > Sequences" but if your preference is to use existing keywords then
    > > IMHO "MERGE Publication Sequences" or "UPDATE Publication Sequences"
    > > are also good options.
    > >
    >
    > I would prefer "COPY Publication Sequences" or "UPDATE Publication
    > Sequences" among the given options. We have a precedence for copy
    > (copy_data) in publication command parameters, so, COPY could be a
    > better option.
    >
    
    If not SYNC, then COPY looks the next best option to me.
    
    thanks
    Shveta
    
    
    
    
  372. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-09T07:00:11Z

    On Thu, Oct 9, 2025 at 5:32 PM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Thu, Oct 9, 2025 at 11:32 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Thu, Oct 9, 2025 at 11:27 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > >
    > > > On Thu, Oct 9, 2025 at 10:14 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > >
    > > > > On Wed, Oct 8, 2025 at 9:13 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > > > >
    > > > > > On Tue, Oct 7, 2025 at 5:46 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > >
    > > > > >
    > > > > > > > I have one more question: while testing the sequence sync, I found
    > > > > > > > this behavior is documented as well[1], but what's the reasoning
    > > > > > > > behind it?  Why REFRESH PUBLICATION will synchronize only newly added
    > > > > > > > sequences and need to use REFRESH PUBLICATION SEQUENCES to
    > > > > > > > re-synchronize all sequences.
    > > > > > > >
    > > > > > >
    > > > > > > The idea is that REFRESH PUBLICATION should behave similarly for
    > > > > > > tables and sequences. This means that this command is primarily used
    > > > > > > to add/remove tables/sequences and copy their respective initial
    > > > > > > contents. The new command REFRESH PUBLICATION SEQUENCES is to sync the
    > > > > > > existing sequences, it shouldn't add any new sequences, now, if it is
    > > > > > > too confusing we can discuss having a different syntax for it.
    > > > > >
    > > > > > Sure, let's discuss this when we get this patch at the start of the
    > > > > > commit queue.
    > > > > >
    > > > >
    > > > > I have pushed the publications related patch. Now, we can discuss this
    > > > > command. I think confusion arises from the fact that both commands use
    > > > > REFRESH.
    > > >
    > > > Right
    > > >
    > > >  So, how about for the second case (sync/copy all existing
    > > > > sequences), we use a different command, some ideas that come to my
    > > > > mind are:
    > > > >
    > > > > Alter Subscription sub1 REPLICATE Publication Sequences;
    > > > > Alter Subscription sub1 RESYNC Publication Sequences;
    > > > > Alter Subscription sub1 SYNC Publication Sequences;
    > > > > Alter Subscription sub1 MERGE Publication Sequences;
    > > > >
    > > > > Among these, the first three require a new keyword to be introduced. I
    > > > > prefer to use existing keyword if possible. Any ideas?
    > > >
    > > > I would have preferred "Alter Subscription sub1 SYNC Publication
    > > > Sequences" but if your preference is to use existing keywords then
    > > > IMHO "MERGE Publication Sequences" or "UPDATE Publication Sequences"
    > > > are also good options.
    > > >
    > >
    > > I would prefer "COPY Publication Sequences" or "UPDATE Publication
    > > Sequences" among the given options. We have a precedence for copy
    > > (copy_data) in publication command parameters, so, COPY could be a
    > > better option.
    > >
    >
    > If not SYNC, then COPY looks the next best option to me.
    >
    
    Something about all these ideas seems strange to me:
    
    I think the "ALTER SUBSCRIPTION sub REFRESH PUBLICATION" command has
    the word PUBLICATION in it because it's the PUBLICATION has changed
    (stuff added/removed), so we need to refresh it.
    
    OTOH, the synchronisation of *existing* sequences is different - this
    is more like the subscription saying "Just get me updated values for
    the sequences I already know about". Therefore, I don't think the word
    PUBLICATION is relevant here.
    
    ~~
    
    So my suggestion is very different.  Just this:
    "ALTER SUBSCRIPTION sub REFRESH SEQUENCES"
    
    I feel this is entirely consistent, because:
    
    PUBLICATION objects have changed. Refresh me the new objects => ALTER
    SUBSCRIPTION sub REFRESH PUBLICATION;
    
    SEQUENCE values have changed. Refresh me the new values => ALTER
    SUBSCRIPTION sub REFRESH SEQUENCES;
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  373. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-09T07:22:33Z

    On Thu, Oct 9, 2025 at 12:30 PM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > I think the "ALTER SUBSCRIPTION sub REFRESH PUBLICATION" command has
    > the word PUBLICATION in it because it's the PUBLICATION has changed
    > (stuff added/removed), so we need to refresh it.
    >
    > OTOH, the synchronisation of *existing* sequences is different - this
    > is more like the subscription saying "Just get me updated values for
    > the sequences I already know about". Therefore, I don't think the word
    > PUBLICATION is relevant here.
    >
    > ~~
    >
    > So my suggestion is very different.  Just this:
    > "ALTER SUBSCRIPTION sub REFRESH SEQUENCES"
    >
    > I feel this is entirely consistent, because:
    >
    > PUBLICATION objects have changed. Refresh me the new objects => ALTER
    > SUBSCRIPTION sub REFRESH PUBLICATION;
    >
    > SEQUENCE values have changed. Refresh me the new values => ALTER
    > SUBSCRIPTION sub REFRESH SEQUENCES;
    
    I prefer this suggestion over the previous proposal so +1 from my side.
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
    
    
    
  374. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-09T08:16:28Z

    On Thu, Oct 9, 2025 at 12:30 PM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Something about all these ideas seems strange to me:
    >
    > I think the "ALTER SUBSCRIPTION sub REFRESH PUBLICATION" command has
    > the word PUBLICATION in it because it's the PUBLICATION has changed
    > (stuff added/removed), so we need to refresh it.
    >
    > OTOH, the synchronisation of *existing* sequences is different - this
    > is more like the subscription saying "Just get me updated values for
    > the sequences I already know about". Therefore, I don't think the word
    > PUBLICATION is relevant here.
    >
    
    makes sense.
    
    > ~~
    >
    > So my suggestion is very different.  Just this:
    > "ALTER SUBSCRIPTION sub REFRESH SEQUENCES"
    >
    
    +1.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  375. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-09T09:37:55Z

    On Thu, 9 Oct 2025 at 12:30, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > On Thu, Oct 9, 2025 at 5:32 PM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Thu, Oct 9, 2025 at 11:32 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Thu, Oct 9, 2025 at 11:27 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > > >
    > > > > On Thu, Oct 9, 2025 at 10:14 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > >
    > > > > > On Wed, Oct 8, 2025 at 9:13 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > > > > >
    > > > > > > On Tue, Oct 7, 2025 at 5:46 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > > > > > >
    > > > > > >
    > > > > > > > > I have one more question: while testing the sequence sync, I found
    > > > > > > > > this behavior is documented as well[1], but what's the reasoning
    > > > > > > > > behind it?  Why REFRESH PUBLICATION will synchronize only newly added
    > > > > > > > > sequences and need to use REFRESH PUBLICATION SEQUENCES to
    > > > > > > > > re-synchronize all sequences.
    > > > > > > > >
    > > > > > > >
    > > > > > > > The idea is that REFRESH PUBLICATION should behave similarly for
    > > > > > > > tables and sequences. This means that this command is primarily used
    > > > > > > > to add/remove tables/sequences and copy their respective initial
    > > > > > > > contents. The new command REFRESH PUBLICATION SEQUENCES is to sync the
    > > > > > > > existing sequences, it shouldn't add any new sequences, now, if it is
    > > > > > > > too confusing we can discuss having a different syntax for it.
    > > > > > >
    > > > > > > Sure, let's discuss this when we get this patch at the start of the
    > > > > > > commit queue.
    > > > > > >
    > > > > >
    > > > > > I have pushed the publications related patch. Now, we can discuss this
    > > > > > command. I think confusion arises from the fact that both commands use
    > > > > > REFRESH.
    > > > >
    > > > > Right
    > > > >
    > > > >  So, how about for the second case (sync/copy all existing
    > > > > > sequences), we use a different command, some ideas that come to my
    > > > > > mind are:
    > > > > >
    > > > > > Alter Subscription sub1 REPLICATE Publication Sequences;
    > > > > > Alter Subscription sub1 RESYNC Publication Sequences;
    > > > > > Alter Subscription sub1 SYNC Publication Sequences;
    > > > > > Alter Subscription sub1 MERGE Publication Sequences;
    > > > > >
    > > > > > Among these, the first three require a new keyword to be introduced. I
    > > > > > prefer to use existing keyword if possible. Any ideas?
    > > > >
    > > > > I would have preferred "Alter Subscription sub1 SYNC Publication
    > > > > Sequences" but if your preference is to use existing keywords then
    > > > > IMHO "MERGE Publication Sequences" or "UPDATE Publication Sequences"
    > > > > are also good options.
    > > > >
    > > >
    > > > I would prefer "COPY Publication Sequences" or "UPDATE Publication
    > > > Sequences" among the given options. We have a precedence for copy
    > > > (copy_data) in publication command parameters, so, COPY could be a
    > > > better option.
    > > >
    > >
    > > If not SYNC, then COPY looks the next best option to me.
    > >
    >
    > Something about all these ideas seems strange to me:
    >
    > I think the "ALTER SUBSCRIPTION sub REFRESH PUBLICATION" command has
    > the word PUBLICATION in it because it's the PUBLICATION has changed
    > (stuff added/removed), so we need to refresh it.
    >
    > OTOH, the synchronisation of *existing* sequences is different - this
    > is more like the subscription saying "Just get me updated values for
    > the sequences I already know about". Therefore, I don't think the word
    > PUBLICATION is relevant here.
    >
    > ~~
    >
    > So my suggestion is very different.  Just this:
    > "ALTER SUBSCRIPTION sub REFRESH SEQUENCES"
    >
    > I feel this is entirely consistent, because:
    >
    > PUBLICATION objects have changed. Refresh me the new objects => ALTER
    > SUBSCRIPTION sub REFRESH PUBLICATION;
    >
    > SEQUENCE values have changed. Refresh me the new values => ALTER
    > SUBSCRIPTION sub REFRESH SEQUENCES;
    
    +1 for this syntax. Here is an updated patch having the changes for the same.
    
    Regards,
    Vignesh
    
  376. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-10T07:33:30Z

    On Thu, Oct 9, 2025 at 3:08 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > >
    > > So my suggestion is very different.  Just this:
    > > "ALTER SUBSCRIPTION sub REFRESH SEQUENCES"
    > >
    > > I feel this is entirely consistent, because:
    > >
    > > PUBLICATION objects have changed. Refresh me the new objects => ALTER
    > > SUBSCRIPTION sub REFRESH PUBLICATION;
    > >
    > > SEQUENCE values have changed. Refresh me the new values => ALTER
    > > SUBSCRIPTION sub REFRESH SEQUENCES;
    >
    > +1 for this syntax. Here is an updated patch having the changes for the same.
    >
    
    Few comments:
    =============
    1.
    + /* From version 19, inclusion of sequences in the target is supported */
    + if (server_version >= 190000)
    + appendStringInfo(&cmd,
    + "UNION ALL\n"
    + "  SELECT DISTINCT s.schemaname, s.sequencename, NULL::int2vector AS
    attrs, 'S'::\"char\" AS relkind\n"
    
    Instead of hard coding 'S', can we use RELKIND_SEQUENCE?
    
    2.
      else
      {
      tableRow[2] = NAMEARRAYOID;
    - appendStringInfoString(&cmd, "SELECT DISTINCT t.schemaname, t.tablename \n");
    + appendStringInfoString(&cmd, "SELECT DISTINCT t.schemaname, t.tablename\n");
    
    Why the above change?
    
    3.
    + pubisseq = (relinfo->relkind == RELKIND_SEQUENCE);
    + subisseq = (relkind == RELKIND_SEQUENCE);
    +
    + /*
    + * Allow RELKIND_RELATION and RELKIND_PARTITIONED_TABLE to be
    + * treated interchangeably, but ensure that sequences
    + * (RELKIND_SEQUENCE) match exactly on both publisher and
    + * subscriber.
    + */
    + if (pubisseq != subisseq)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    
    We can directly compare relkind here and avoid having two extra
    variables. The same code is present in AlterSubscription_refresh. So,
    we can make the similar change there as well. BTW, the same scenario
    could happen between table and sequences, no? If so, then we should
    deal with that as well. It would be better if can make these checks as
    part of CheckSubscriptionRelkind().
    
    4.
    + errmsg("relation \"%s.%s\" has relkind \"%c\" on the publisher but
    relkind \"%c\" on the subscriber",
    
    I would like this message to be bit short and speak in terms of source
    and target, something like: errmsg("relation \"%s.%s\" type mismatch:
    source \"%c\", target \"%c\"")
    
    5.
    + *
    + * XXX: Currently, a replication slot is created for all
    + * subscriptions, including those for sequence-only publications.
    + * However, this is unnecessary, as incremental synchronization of
    + * sequences is not supported.
    
    Can we try to avoid creating slot/origin for sequence-only
    subscriptions? We don't want to make code complicated due to this, so
    try to create a top-up patch so that we can evaluate this change
    separately?
    
    6.
    @@ -2403,11 +2503,15 @@ check_publications_origin(WalReceiverConn
    *wrconn, List *publications,
    for (i = 0; i < subrel_count; i++)
    {
    Oid relid = subrel_local_oids[i];
    - char    *schemaname = get_namespace_name(get_rel_namespace(relid));
    - char    *tablename = get_rel_name(relid);
    - appendStringInfo(&cmd, "AND NOT (N.nspname = '%s' AND C.relname = '%s')\n",
    - schemaname, tablename);
    + if (get_rel_relkind(relid) != RELKIND_SEQUENCE)
    
    Why do we have the above check in the 0002 patch? We can add some
    comments to clarify the same, if it is required. Also, we should do
    this origin check during ALTER SUBSCRIPTION … REFRESH command as we
    don't have incremental WAL based filtering of origin for sequences.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  377. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-11T14:12:29Z

    On Fri, 10 Oct 2025 at 13:03, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Oct 9, 2025 at 3:08 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > >
    > > > So my suggestion is very different.  Just this:
    > > > "ALTER SUBSCRIPTION sub REFRESH SEQUENCES"
    > > >
    > > > I feel this is entirely consistent, because:
    > > >
    > > > PUBLICATION objects have changed. Refresh me the new objects => ALTER
    > > > SUBSCRIPTION sub REFRESH PUBLICATION;
    > > >
    > > > SEQUENCE values have changed. Refresh me the new values => ALTER
    > > > SUBSCRIPTION sub REFRESH SEQUENCES;
    > >
    > > +1 for this syntax. Here is an updated patch having the changes for the same.
    > >
    >
    > Few comments:
    > =============
    > 1.
    > + /* From version 19, inclusion of sequences in the target is supported */
    > + if (server_version >= 190000)
    > + appendStringInfo(&cmd,
    > + "UNION ALL\n"
    > + "  SELECT DISTINCT s.schemaname, s.sequencename, NULL::int2vector AS
    > attrs, 'S'::\"char\" AS relkind\n"
    >
    > Instead of hard coding 'S', can we use RELKIND_SEQUENCE?
    
    Modified
    
    > 2.
    >   else
    >   {
    >   tableRow[2] = NAMEARRAYOID;
    > - appendStringInfoString(&cmd, "SELECT DISTINCT t.schemaname, t.tablename \n");
    > + appendStringInfoString(&cmd, "SELECT DISTINCT t.schemaname, t.tablename\n");
    >
    > Why the above change?
    
    This is not required, removed this change
    
    > 3.
    > + pubisseq = (relinfo->relkind == RELKIND_SEQUENCE);
    > + subisseq = (relkind == RELKIND_SEQUENCE);
    > +
    > + /*
    > + * Allow RELKIND_RELATION and RELKIND_PARTITIONED_TABLE to be
    > + * treated interchangeably, but ensure that sequences
    > + * (RELKIND_SEQUENCE) match exactly on both publisher and
    > + * subscriber.
    > + */
    > + if (pubisseq != subisseq)
    > + ereport(ERROR,
    > + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    >
    > We can directly compare relkind here and avoid having two extra
    > variables. The same code is present in AlterSubscription_refresh. So,
    > we can make the similar change there as well. BTW, the same scenario
    > could happen between table and sequences, no? If so, then we should
    > deal with that as well. It would be better if can make these checks as
    > part of CheckSubscriptionRelkind().
    
    Modified
    
    > 4.
    > + errmsg("relation \"%s.%s\" has relkind \"%c\" on the publisher but
    > relkind \"%c\" on the subscriber",
    >
    > I would like this message to be bit short and speak in terms of source
    > and target, something like: errmsg("relation \"%s.%s\" type mismatch:
    > source \"%c\", target \"%c\"")
    
    Modified
    
    > 5.
    > + *
    > + * XXX: Currently, a replication slot is created for all
    > + * subscriptions, including those for sequence-only publications.
    > + * However, this is unnecessary, as incremental synchronization of
    > + * sequences is not supported.
    >
    > Can we try to avoid creating slot/origin for sequence-only
    > subscriptions? We don't want to make code complicated due to this, so
    > try to create a top-up patch so that we can evaluate this change
    > separately?
    
    I will do this and post it along with the next version
    
    > 6
    > @@ -2403,11 +2503,15 @@ check_publications_origin(WalReceiverConn
    > *wrconn, List *publications,
    > for (i = 0; i < subrel_count; i++)
    > {
    > Oid relid = subrel_local_oids[i];
    > - char    *schemaname = get_namespace_name(get_rel_namespace(relid));
    > - char    *tablename = get_rel_name(relid);
    > - appendStringInfo(&cmd, "AND NOT (N.nspname = '%s' AND C.relname = '%s')\n",
    > - schemaname, tablename);
    > + if (get_rel_relkind(relid) != RELKIND_SEQUENCE)
    >
    > Why do we have the above check in the 0002 patch? We can add some
    > comments to clarify the same, if it is required. Also, we should do
    > this origin check during ALTER SUBSCRIPTION … REFRESH command as we
    > don't have incremental WAL based filtering of origin for sequences.
    
    This check is not required, as there is a scenario where  N1
    replicates sequences to N2 and N2 replicates sequences to N3. This
    warning will be helpful
    
    The attached patch has the changes for the same.
    
    Regards,
    Vignesh
    
  378. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-13T00:59:21Z

    HI Vignesh,
    
    Here are some minor review comments for patches 0001 and 0002.
    
    ////////////////////
    Patch 0001
    ////////////////////
    
    AlterSubscription:
    
    1.1.
      (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    - errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled
    subscriptions")));
    + errmsg("ALTER SUBSCRIPTION ... REFRESH PUBLICATION is not allowed
    for disabled subscriptions")));
    
    
    Maybe this could use a parameter substitution like:
    
    errmsg("%s is not allowed for disabled subscriptions", "ALTER
    SUBSCRIPTION ... REFRESH PUBLICATION");
    
    That way (in preparation for the next patch), there will be only 1
    message requiring translation.
    
    ////////////////////
    Patch 0002
    ////////////////////
    
    Commit message:
    
    2.1
    "This command update the sequence entries present in the..."
    
    /update/updates/
    
    ======
    
    AlterSubscription:
    
    2.2
    + if (!sub->enabled)
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("ALTER SUBSCRIPTION ... REFRESH SEQUENCES is not allowed for
    disabled subscriptions"));
    
    Can use the same message with parameter substitution as mentioned above (#1.1)
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  379. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-13T06:59:59Z

    On Sat, Oct 11, 2025 at 7:42 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > The attached patch has the changes for the same.
    >
    
    I have a few more comments on 0002 patch:
    1. In check_publications_origin(), isn't it better to name
    check_table_sync as check_sync as it is used for both tables and
    sequences?
    
    2. In check_publications_origin(), for all three queries, only the
    following part seems to be different:
    
    < 19
    "     LATERAL pg_get_publication_tables(P.pubname) GPT\n"
    >=19
    only_sequences
    "     LATERAL pg_get_publication_sequences(P.pubname) GPT\n"
    else
    "     CROSS JOIN LATERAL (SELECT relid FROM
    pg_get_publication_tables(P.pubname) UNION ALL"
    "                    SELECT relid FROM
    pg_get_publication_sequences(P.pubname)) GPT\n"
    
    2A. Can this part of the query be made dynamic, and then we can have a
    query instead of three? If so, I think it would simplify the code.
    What do you think?
    2B. Can we add/modify the comment atop check_publications_origin to
    mention about sequence case?
    
    3.
     void
    -CheckSubscriptionRelkind(char relkind, const char *nspname,
    +CheckSubscriptionRelkind(char relkind, char pubrelkind, const char *nspname,
      const char *relname)
     {
    - if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
    + if (relkind != RELKIND_RELATION &&
    + relkind != RELKIND_PARTITIONED_TABLE &&
    + relkind != RELKIND_SEQUENCE)
      ereport(ERROR,
      (errcode(ERRCODE_WRONG_OBJECT_TYPE),
      errmsg("cannot use relation \"%s.%s\" as logical replication target",
      nspname, relname),
      errdetail_relkind_not_supported(relkind)));
    +
    + if (pubrelkind == '\0')
    + return;
    
    This looks ad hoc. I think it would be better if the caller passes the
    same value for local and remote relkind to this function. And
    accordingly, change the name of the first two parameters.
    
    4.
    +static void
    +AlterSubscription_refresh_seq(Subscription *sub)
    …
    + check_publications_origin(wrconn, sub->publications, false,
    +   sub->retaindeadtuples, sub->origin, NULL, 0,
    +   sub->name, true);
    
    Write a few comments to explain why it is necessary to check origins
    in this case. If the additional comments atop
    check_publications_origin() cover this case, then it's okay as it is.
    
    5.
    AlterSubscription_refresh()
    - sub_remove_rels[remove_rel_len].relid = relid;
    - sub_remove_rels[remove_rel_len++].state = state;
    …
    - char originname[NAMEDATALEN];
    + SubRemoveRels *rel = palloc(sizeof(SubRemoveRels));
    +
    + rel->relid = relid;
    + rel->state = state;
    +
    + sub_remove_rels = lappend(sub_remove_rels, rel);
    
    Why do we change an offset based array into list? It looks slightly
    odd that in the same function one of the other similar array
    pubrel_local_oids is not converted when the above is converted. And
    even if we do so, I don't think we need a retail free
    (list_free_deep(sub_remove_rels);) as the memory allocation here is in
    portal context which should be reset by end of the current statement
    execution.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  380. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-13T07:27:38Z

    Please find few initial comments for 002:
    
    
    1)
    Patch commit msg says:
    
    "This patch adds support for a new SQL command:
    ALTER SUBSCRIPTION ... REFRESH SEQUENCES
    This command update the sequence entries present in the
    pg_subscription_rel catalog table with the INIT state to trigger
    resynchronization."
    
    But AlterSubscription_refresh_seq actually updates the state to DATASYNC.
    
    2)
    CheckSubscriptionRelkind()
    
    + /*
    + * Allow RELKIND_RELATION and RELKIND_PARTITIONED_TABLE to be treated
    + * interchangeably, but ensure that sequences (RELKIND_SEQUENCE) match
    + * exactly on both publisher and subscriber.
    + */
    + if ((relkind == RELKIND_SEQUENCE && pubrelkind != RELKIND_SEQUENCE) ||
    + ((relkind == RELKIND_RELATION || relkind == RELKIND_PARTITIONED_TABLE) &&
    + !(pubrelkind == RELKIND_RELATION || pubrelkind == RELKIND_PARTITIONED_TABLE)))
    + ereport(ERROR,
    + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    + errmsg("relation \"%s.%s\" type mismatch: source \"%s\", target \"%s\"",
    +    nspname, relname,
    +    pubrelkind == RELKIND_SEQUENCE ? "sequence" : "table",
    +    relkind == RELKIND_SEQUENCE ? "sequence" : "table"));
    
    Shall we simplify the check as:
    if ((relkind == RELKIND_SEQUENCE && pubrelkind != RELKIND_SEQUENCE) ||
         (relkind != RELKIND_SEQUENCE && pubrelkind == RELKIND_SEQUENCE))
    
    3)
    CreateSubscription()
    + relations = fetch_relation_list(wrconn, publications);
    
    Can we please rename 'relations' to 'pubrels', as the latter gives
    more clarity and is in consistency with AlterSubscription_refresh().
    
    4)
    - CheckSubscriptionRelkind(get_rel_relkind(relid),
    + CheckSubscriptionRelkind(relkind, relinfo->relkind,
      rv->schemaname, rv->relname);
    
    We are passing 2 relkinds now to CheckSubscriptionRelkind() but it is
    difficult to understand which is which. Can we please rename relinfo
    as pubrelinfo so that we get clarity. This is in both
    CreateSubscription and AlterSubscription_refresh/
    
    5)
    CheckSubscriptionRelkind
    + if (pubrelkind == '\0')
    + return;
    
    Do you think, we shall write a comment in the function header that the
    caller who wants to verify only the supported type should pass
    pubrelkind as '\0'?
    
    6)
    Should we update doc of pg_subscription_rel where it says this:
    
    This catalog only contains tables known to the subscription after
    running either CREATE SUBSCRIPTION or ALTER SUBSCRIPTION ... REFRESH
    PUBLICATION.
    
    thanks
    Shveta
    
    
    
    
  381. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-10-14T03:13:15Z

    Dear Vignesh,
    
    Thanks for updating the patch. Here are comments for 0002.
    
    ```
    +       if (pubrelkind == '\0')
    +               return;
    ```
    
    Instead of adding this part, can we provide another function which only checks
    the type mismatch? New one can be called from CreateSubscription() and
    AlterSubscription_refresh().
    
    ```
    +#include "nodes/primnodes.h"
    ...
    +typedef struct SubscriptionRelKind
    +{
    +       RangeVar   *rv;
    +       char            relkind;
    +}
    ```
    
    The data structure is used in subscriptioncmds.c. Can we move the definition to
    the file?
    Also, `relkind` indicates the type of relation on publisher. Can you clarify
    the point like `relkind_on_pub`?
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
    
    
  382. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-14T05:21:11Z

    On Mon, Oct 13, 2025 at 12:57 PM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > Please find few initial comments for 002:
    >
    
    7)
    
    Currently CREATE SUB makes the state 'i' for sequences in
    pg_subscription_rel while ALTER SUB REFRESH SEQ makes the state as
    'd'. I think we do not need to maintain 2 different states here. We
    can have both CREATE SUB and ALTER SUB make it as 'i'. For tables, we
    need multiple states as we first do copy and then apply changes as
    well. But for sequences, that is not the case. So we can have only 2
    states: 'i' (needs sync) and 'r' (ready) for sequences. We can update
    comments to indicate the same.
    
    thanks
    Shveta
    
    
    
    
  383. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-14T10:02:52Z

    On Tuesday, October 14, 2025 11:13 AM Kuroda, Hayato/黒田 隼人 <kuroda.hayato@fujitsu.com> wrote:
    > Dear Vignesh,
    > 
    > Thanks for updating the patch. Here are comments for 0002.
    > 
    > ```
    > +       if (pubrelkind == '\0')
    > +               return;
    > ```
    > 
    > Instead of adding this part, can we provide another function which only checks
    > the type mismatch? New one can be called from CreateSubscription() and
    > AlterSubscription_refresh().
    
    Per analysis, the checks in the function should be performed for all the cases,
    so I did not add a new function.
    
    > 
    > ```
    > +#include "nodes/primnodes.h"
    > ...
    > +typedef struct SubscriptionRelKind
    > +{
    > +       RangeVar   *rv;
    > +       char            relkind;
    > +}
    > ```
    > 
    > The data structure is used in subscriptioncmds.c. Can we move the definition
    > to the file?
    > Also, `relkind` indicates the type of relation on publisher. Can you clarify the
    > point like `relkind_on_pub`?
    
    I chose to change the type name from SubscriptionRelKind to
    PublicationRelKind since it is used to describe the relation on publisher.
    
    Attach the latest patch that includes the following changes:
    
    0001:
    * Addressed Peter's comments[1]
    
    0002:
    * Addressed Amit's comments[2]
    * Addressed Shveta's comments[3]
    * Addressed Kuroda's comments[4]
    * Fixed an issue where check_publications_origin checked
      partitions and ancestors of sequences that were unnecessary.
    * Fixed an issue where check_publications_origin performed redundant checks on
      the origin, even when origin option is set to ANY.
    * Fixed an issue where check_publications_origin unnecessarily checked sequences
      when only table checks are required, particularly when retain_dead_tuples is
      true and the origin is set to ANY.
    * Changed CheckSubscriptionRelkind to do the relkind match check during replication
      as well. This ensures detection of relkind mismatches, when a local table on
      the subscriber is dropped and subsequently replaced by a new sequence with the
      same name after the initial sync.
    
    0003~0005:
    Unchanged.
    
    TODO:
    * The latest comment from Shveta[5].
    * The comment from Amit[6] to avoid creating slot/origin for sequence only subscription.
    
    [1] https://www.postgresql.org/message-id/CAHut%2BPuDCMu5QDmAo%2BMW0hKSThACfqfaPBGcwrBOUFE3RUPP%3Dw%40mail.gmail.com
    [2] https://www.postgresql.org/message-id/CAA4eK1%2BSMY-dEhnFw8wXYSygk4Xr%2BSZJ-zEnuhxb%2BFmFrN0AzQ%40mail.gmail.com
    [3] https://www.postgresql.org/message-id/CAJpy0uC5H0jtmUEN8ES_PAMaYCfjmqEVuJiCdB%3DAa98ivqc9FA%40mail.gmail.com
    [4] https://www.postgresql.org/message-id/OSCPR01MB149667963060BB6A068B275B9F5EBA%40OSCPR01MB14966.jpnprd01.prod.outlook.com
    [5] https://www.postgresql.org/message-id/CAJpy0uBpxor5EaSDFd0u2kXV5zgEkSq7g6iaSNwVXY0U1Rk4iA%40mail.gmail.com
    [6] https://www.postgresql.org/message-id/CAA4eK1J%3Dgc8WXVc2Hy0Xcq4KtWU-z-dxBiZHbT62jz3QPBZ5CQ%40mail.gmail.com
    
    Best Regards,
    Hou zj
     
    
  384. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-14T10:03:16Z

    On Monday, October 13, 2025 3:28 PM shveta malik <shveta.malik@gmail.com> wrote:
    > Please find few initial comments for 002:
    
    Thanks for the comments.
    
    > 
    > 
    > 5)
    > CheckSubscriptionRelkind
    > + if (pubrelkind == '\0')
    > + return;
    > 
    > Do you think, we shall write a comment in the function header that the caller
    > who wants to verify only the supported type should pass pubrelkind as '\0'?
    
    This check is removed due to some other changes.
    
    All other comments have been addressed in the latest version.
    
    Best Regards,
    Hou zj
    
  385. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-14T10:03:35Z

    On Monday, October 13, 2025 3:00 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > 
    > On Sat, Oct 11, 2025 at 7:42 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached patch has the changes for the same.
    > >
    > 
    > 5.
    > AlterSubscription_refresh()
    > - sub_remove_rels[remove_rel_len].relid = relid;
    > - sub_remove_rels[remove_rel_len++].state = state;
    > …
    > - char originname[NAMEDATALEN];
    > + SubRemoveRels *rel = palloc(sizeof(SubRemoveRels));
    > +
    > + rel->relid = relid;
    > + rel->state = state;
    > +
    > + sub_remove_rels = lappend(sub_remove_rels, rel);
    > 
    > Why do we change an offset based array into list? It looks slightly
    > odd that in the same function one of the other similar array
    > pubrel_local_oids is not converted when the above is converted. And
    > even if we do so, I don't think we need a retail free
    > (list_free_deep(sub_remove_rels);) as the memory allocation here is in
    > portal context which should be reset by end of the current statement
    > execution.
    
    when sub_remove_rels was Array type, we used subrel_count as the initial size of
    this array, but this count means the number of both the table and sequences. So
    it allocates some unnecessary space for it, which is why we changed it to List.
    
    Based on above, I kept the current style for now but removed the list_free.
    
    All other comments have been addressed in the latest version.
    
    Best Regards,
    Hou zj
    
  386. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-14T10:03:41Z

    On Monday, October 13, 2025 8:59 AM Peter Smith <smithpb2250@gmail.com> wrote:
    > 
    > HI Vignesh,
    > 
    > Here are some minor review comments for patches 0001 and 0002.
    
    Thanks for the comments. I have addressed them in the latest version.
    
    Best Regards,
    Hou zj
    
  387. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-14T10:06:34Z

    On Tue, Oct 14, 2025 at 3:33 PM Zhijie Hou (Fujitsu)
    <houzj.fnst@fujitsu.com> wrote:
    >
    > 0003~0005:
    > Unchanged.
    >
    > TODO:
    > * The latest comment from Shveta[5].
    > * The comment from Amit[6] to avoid creating slot/origin for sequence only subscription.
    >
    
    Few comments on 0003 and 0004 based on previous version of the patch.
    As those are not changed, so I assume they apply for the new version
    as well.
    
    1. invalidate_syncing_table_states is changed to
    InvalidateRelationStates. We could still retain syncing in it and name
    it as InvalidateSyncingRelationStates
    
    2.
    - /* Process any tables that are being synchronized in parallel. */
    + /*
    + * Process any tables that are being synchronized in parallel and any
    + * newly added relations.
    + */
      ProcessSyncingRelations(commit_data.end_lsn);
    
      pgstat_report_activity(STATE_IDLE, NULL);
    @@ -1364,7 +1372,10 @@ apply_handle_prepare(StringInfo s)
    
      in_remote_transaction = false;
    
    - /* Process any tables that are being synchronized in parallel. */
    + /*
    + * Process any tables that are being synchronized in parallel and any
    + * newly added relations.
    + */
      ProcessSyncingRelations(prepare_data.end_lsn);
    
    In the first line of comment, it is mentioned as tables and in the
    second line, the relations are mentioned. I think as part of this it
    can process sequences as well if any are added. I wonder whether this
    (while applying prepare/commit) is the right time to invoke it for
    sequences. The apply worker do need to invoke sequencesync worker if
    required but not sure if this is the right place.
    
    3.
    @@ -378,9 +378,6 @@ ProcessSyncingTablesForApply(XLogRecPtr current_lsn)
    
      Assert(!IsTransactionState());
    
    - /* We need up-to-date sync state info for subscription tables here. */
    - FetchRelationStates(&started_tx);
    
    I think it is better to let FetchRelationStates be invoked from here
    as it sets the context of further work and makes it easy to understand
    the code flow. We can even do the same for
    ProcessSyncingSequencesForApply().
    
    4.
    @@ -3284,7 +3307,7 @@ FindDeletedTupleInLocalRel(Relation localrel,
    Oid localidxoid,
      */
      LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
      leader = logicalrep_worker_find(MyLogicalRepWorker->subid,
    - InvalidOid, false);
    + InvalidOid, false, false);
    
    …
     extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
    + LogicalRepWorkerType wtype,
      bool only_running);
    
    The third parameter is LogicalRepWorkerType and passing it false in
    the above usage doesn't make sense. Also, we should update comments
    atop logicalrep_worker_find as to why worker_type is required. I want
    to know why subid+relid combination is not sufficient to identify the
    workers uniquely.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  388. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-14T11:37:46Z

    On Tue, Oct 14, 2025 at 3:36 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    
    0001 and 0002 looks good, except this duplicate version checking code below
    in fetch_relation_list [1][2], I mean check_relkind and sequence fetching
    both are related changes and start from version 19, so we can do a single
    check.  Instead of the 'check_relkind' variable name we can change it to
    'support_relkind_seq' or something like that and then we can use this in
    both checks.
    
    
    [1]
    + bool check_relkind = (server_version >= 190000);
    + int column_count = check_columnlist ? (check_relkind ? 4 : 3) : 2;
    
    
    [2]
    + /* From version 19, inclusion of sequences in the target is supported */
    + if (server_version >= 190000)
    + appendStringInfo(&cmd,
    + "UNION ALL\n"
    + "  SELECT DISTINCT s.schemaname, s.sequencename, NULL::int2vector AS
    attrs, " CppAsString2(RELKIND_SEQUENCE) "::\"char\" AS relkind\n"
    + "  FROM pg_catalog.pg_publication_sequences s\n"
    + "  WHERE s.pubname IN (%s)",
    + pub_names->data);
    
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
  389. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-10-14T12:09:16Z

    Dear Hou,
    
    Thanks for updating the patch. Here are comments for recent 0002.
    Others are still being reviewed
    
    01. pg_subscription_rel.h
    ```
    +#include "nodes/primnodes.h"
    ```
    
    The inclusion is not needed because the 
    
    
    02. typedefs.list
    ```
    +SubscriptionRelKind
    ```
    
    Missing update.
    
    03. subscritioncmds.c
    ```
    +#include "catalog/pg_sequence.h"
    ```
    
    I could build without the inclusion. Can you remove?
    
    04. check_publications_origin
    ```
    +
    +       query = "SELECT DISTINCT P.pubname AS pubname\n"
    +                       "FROM pg_publication P,\n"
    +                       "     LATERAL %s GPR\n"
    ...
    ```
    
    pgindent does not like the notation. How aboout chaning the line after the "="?
    I.e.,
    
    ```
    	query =
    		"SELECT DISTINCT P.pubname AS pubname\n"
    		"FROM pg_publication P,\n"
    		"     LATERAL %s GPR\n"
    ...
    ```
    
    05. AddSubscriptionRelState
    
    ```
    	if (HeapTupleIsValid(tup))
    		elog(ERROR, "subscription table %u in subscription %u already exists",
    			 relid, subid);
    ```
    
    Theoretically subid might be the sequence, right? Should we say "relation"
    instead of "table" as well?
    
    06. AlterSubscription_refresh_seq
    ```
    +               /* Get local relation list. */
    ```
    
    In contrast can we say "sequence"?
    
    
    07. check_publications_origin
    ```
    	if (res->status != WALRCV_OK_TUPLES)
    		ereport(ERROR,
    				(errcode(ERRCODE_CONNECTION_FAILURE),
    				 errmsg("could not receive list of replicated tables from the publisher: %s",
    						res->err)));
    ```
    
    Should we say "relations" instead of "tables"? Similar lines are:
    
    ```
    	/* Process tables. */
    ...
    	 * Log a warning if the publisher has subscribed to the same table from
    ```
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED
     
    
  390. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-15T04:11:31Z

    Please find a few more comments on 002:
    
    
    1)
    -   This catalog only contains tables known to the subscription after running
    +   This catalog only contains tables and sequences known to the
    subscription after running
    
    Shall we get rid of 'only' now?
    
    2)
    + * A single sequencesync worker synchronizes all sequences, so
    + * only stop workers when relation kind is not sequence.
    
    This comment refers sequencesync worker which is in future patches. Is it okay?
    
    3)
    UpdateSubscriptionRelState
    
            if (!HeapTupleIsValid(tup))
                    elog(ERROR, "subscription table %u in subscription %u
    does not exist",
                             relid, subid);
    
    table -->relation as AlterSubscription_refresh_seq() also invokes this.
    
    4)
    check_publications_origin :
    
            if (res->status != WALRCV_OK_TUPLES)
                    ereport(ERROR,
                                    (errcode(ERRCODE_CONNECTION_FAILURE),
                                     errmsg("could not receive list of
    replicated tables from the publisher: %s",
                                                    res->err)));
    
    It could be sequences also.
    We can either make it as 'replicated tables and/or sequences' or
    simply 'replicated relations'
    
    5)
    fetch_relation_list:
    Same here:
            if (res->status != WALRCV_OK_TUPLES)
                    ereport(ERROR,
                                    (errcode(ERRCODE_CONNECTION_FAILURE),
                                     errmsg("could not receive list of
    replicated tables from the publisher: %s",
                                                    res->err)));
    
    
    6)
    CreateSubscription:
            /*
             * Connect to remote side to execute requested commands and fetch table
             * info.
             */
    
    We can update this existing comment to mention sequences as well.
    
    thanks
    Shveta
    
    
    
    
  391. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-15T06:00:55Z

    Please find a few comments on 003:
    
    1)
    +#include "replication/logicallauncher.h"
    +#include "replication/origin.h"
    +#include "replication/slot.h"
    
    syncutils.c compiles without these 3 inclusions.
    
    2)
    Should 'table_states_not_ready' be changed to
    'relation_states_not_ready' as now it handles both tables and
    sequences?
    
    3)
    invalidate_syncing_table_states has been changed to
    InvalidateRelationStates. Shall we keep it as
    InvalidateSyncingRelStates()?
    
    4)
    getSubscriptionTables:
    
    - *   Get information about subscription membership for dumpable tables. This
    + *   Get information about subscription membership for dumpable relations. This
    
    Is there a reason that we have changed the comment but not the function name?
    
    thanks
    Shveta
    
    
    
    
  392. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-15T07:03:07Z

    On Tue, Oct 14, 2025 at 5:08 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Tue, Oct 14, 2025 at 3:36 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > 0001 and 0002 looks good,
    >
    
    Thanks, I pushed 0001. I feel it is better to next commit refactoring
    patch v20251014-0003-Reorganize-tablesync-Code-and-Introduce-sy as
    that would be less controversial. What do you think?
    
    > except this duplicate version checking code below in fetch_relation_list [1][2], I mean check_relkind and sequence fetching both are related changes and start from version 19, so we can do a single check.  Instead of the 'check_relkind' variable name we can change it to 'support_relkind_seq' or something like that and then we can use this in both checks.
    >
    
    Sounds reasonable to me.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  393. Re: Logical Replication of sequences

    Chao Li <li.evan.chao@gmail.com> — 2025-10-15T08:28:28Z

    I only reviewed 0003 as I saw Amit mentioned next should be 0003. Over LGTM, I just got one comment:
    
    > 
    > <v20251014-0005-Documentation-for-sequence-synchronization.patch><v20251014-0001-Update-ALTER-SUBSCRIPTION-REFRESH-to-ALTER.patch><v20251014-0002-Introduce-REFRESH-SEQUENCES-for-subscripti.patch><v20251014-0003-Reorganize-tablesync-Code-and-Introduce-sy.patch><v20251014-0004-New-worker-for-sequence-synchronization-du.patch>
    
    
    
    In common.c:
    ```
    -	pg_log_info("reading subscription membership of tables");
    +	pg_log_info("reading subscription membership of relations");
     	getSubscriptionTables(fout);
    ```
    
    0003 is replacing “table” with “relation” everywhere, I think that's because Sequence will be involved. In this place, why the comment is updated, but the function name is unchanged? Looking at the function comment of getSubscriptionTables():
    
    /*
     * getSubscriptionTables
     *    Get information about subscription membership for dumpable relations. This
     *    will be used only in binary-upgrade mode for PG17 or later versions.
     */
    void
    getSubscriptionTables(Archive *fout)
    
    It also mentions “dumpable relations”. Should we update the function to use “relation” as well?
    
    Best regards,
    --
    Chao Li (Evan)
    HighGo Software Co., Ltd.
    https://www.highgo.com/
    
    
    
    
    
  394. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-15T11:20:49Z

    On Wednesday, October 15, 2025 3:03 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    
    > 
    > On Tue, Oct 14, 2025 at 5:08 PM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Tue, Oct 14, 2025 at 3:36 PM Amit Kapila <amit.kapila16@gmail.com>
    > wrote:
    > >
    > > 0001 and 0002 looks good,
    > >
    > 
    > Thanks, I pushed 0001. I feel it is better to next commit refactoring patch
    > v20251014-0003-Reorganize-tablesync-Code-and-Introduce-sy as that would
    > be less controversial. What do you think?
    
    I agree and has reordered the latest patch set.
    
    > 
    > > except this duplicate version checking code below in fetch_relation_list
    > [1][2], I mean check_relkind and sequence fetching both are related changes
    > and start from version 19, so we can do a single check.  Instead of the
    > 'check_relkind' variable name we can change it to 'support_relkind_seq' or
    > something like that and then we can use this in both checks.
    > >
    > 
    > Sounds reasonable to me.
    
    Changed as suggested.
    
    Here is the new version patch set which includes the following changes:
    
    0001:
    * Addressed comments from Shveta[1] and Chao li[2].
    
    0002
    * Addressed Shveta[3], Kuroda-San[4] and Dilip's comments[5].
    
    TODO:
    * The comments on 0003 patch by Amit[6].
    * The comment from Amit[7] to avoid creating slot/origin for sequence only subscription.
    
    [1] https://www.postgresql.org/message-id/CAJpy0uCSKChetEw1buBrZu3vAV8OYv3X9MygNxKHw5WWzMd1Gg%40mail.gmail.com 
    [2] https://www.postgresql.org/message-id/158C2EDB-D505-46A6-996D-296EC1B3ACE2%40gmail.com
    [3] https://www.postgresql.org/message-id/CAJpy0uCPuTLEkuC7kbXwvyUuxrtKOhDb9A3ti6EhOKgzMNkbcQ%40mail.gmail.com
    [4] https://www.postgresql.org/message-id/OSCPR01MB14966B8BB27B784674506C9A8F5EBA%40OSCPR01MB14966.jpnprd01.prod.outlook.com
    [5] https://www.postgresql.org/message-id/CAA4eK1%2BHb4H9z8C5kiuc42%3Dw%3DPi9dQAioJW%3D2OSr9eAnpoxF6w%40mail.gmail.com
    [6] https://www.postgresql.org/message-id/CAA4eK1J8UYFPgcM5b0aHvbRT_3pVNUpnpvypQU5vqk4Uu%3DmXVg%40mail.gmail.com
    [7] https://www.postgresql.org/message-id/CAA4eK1J%3Dgc8WXVc2Hy0Xcq4KtWU-z-dxBiZHbT62jz3QPBZ5CQ%40mail.gmail.com
    
    Best Regards,
    Hou zj
    
    
    
  395. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-15T11:20:52Z

    On Wednesday, October 15, 2025 12:12 PM shveta malik <shveta.malik@gmail.com> wrote:
    > 
    > Please find a few more comments on 002:
    ...
    > Please find a few comments on 003:
    ...
    
    Thanks for the comments, I have addressed them in latest version.
    
    Best Regards,
    Hou zj
    
  396. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-15T11:21:03Z

    On Tuesday, October 14, 2025 8:09 PM Kuroda, Hayato/黒田 隼人 <kuroda.hayato@fujitsu.com> wrote:
    > 
    > Dear Hou,
    > 
    > Thanks for updating the patch. Here are comments for recent 0002.
    > Others are still being reviewed
    
    Thanks for the comments.
    
    > 04. check_publications_origin
    > ```
    > +
    > +       query = "SELECT DISTINCT P.pubname AS pubname\n"
    > +                       "FROM pg_publication P,\n"
    > +                       "     LATERAL %s GPR\n"
    > ...
    > pgindent does not like the notation. How aboout chaning the line after the "="?
    > I.e.,
    > 
    > ```
    > 	query =
    > 		"SELECT DISTINCT P.pubname AS pubname\n"
    > 		"FROM pg_publication P,\n"
    > 		"     LATERAL %s GPR\n"
    > ...
    > ```
    
    I chose to accept what pgindent suggests instead of doing more adjustments.
    
    All other comments have been addressed in the latest version.
    
    Best Regards,
    Hou zj 
    
  397. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-15T11:21:17Z

    On Wednesday, October 15, 2025 4:28 PM Chao Li <li.evan.chao@gmail.com>  wrote:
    
    > /*
    >  * getSubscriptionTables
    >  *    Get information about subscription membership for dumpable relations. This
    >  *    will be used only in binary-upgrade mode for PG17 or later versions.
    >  */
    > void
    > getSubscriptionTables(Archive *fout)
    > 
    > It also mentions “dumpable relations”. Should we update the function to use
    > “relation” as well?
    
    Thanks for the comments ! It has been addressed in the latest version.
    
    (BTW, it would be highly appreciated if you can send emails in plain text format.
    The current email is in HTML mode, which can make inline replies a bit
    challenging. Plain text is also the traditional style preferred by the community :) .)
    
    Best Regards,
    Hou zj
    
    
    
  398. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-16T09:59:20Z

    On Wed, Oct 15, 2025 at 4:51 PM Zhijie Hou (Fujitsu)
    <houzj.fnst@fujitsu.com> wrote:
    >
    > Here is the new version patch set which includes the following changes:
    >
    
    I have pushed the first patch. Kindly rebase and share the remaining patches.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  399. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-16T11:23:39Z

    On Thursday, October 16, 2025 5:59 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > 
    > On Wed, Oct 15, 2025 at 4:51 PM Zhijie Hou (Fujitsu)
    > <houzj.fnst@fujitsu.com> wrote:
    > >
    > > Here is the new version patch set which includes the following changes:
    > >
    > 
    > I have pushed the first patch. Kindly rebase and share the remaining patches.
    
    Thanks! Here is the remaining patches, which addressed all pending comments.
    
    Regarding whether we can avoid creating slot/origin for seq-only publication.
    I think the main challenge lies in ensuring the apply worker operates smoothly
    without a replication slot. Currently, the apply worker uses the
    START_REPLICATION command with a replication slot to acquire the slot on the
    publisher. To bypass this, it's essential to skip starting the replication and
    specifically, avoid entering the LogicalRepApplyLoop().
    
    To address this, I thought to implement a separate loop dedicated to
    sequence-only subscriptions. Within this loop, the apply worker would only call
    functions like ProcessSyncingSequencesForApply() to manage sequence
    synchronization while periodically checking for any new tables added to the
    subscription. If new tables are detected, the apply worker would exit this loop
    and enter the LogicalRepApplyLoop().
    
    I chose not to consider allowing the START_REPLICATION command to operate
    without a logical slot, as it seems like an unconventional approach requiring
    modifications in walsender and to skip logical decoding and related processes.
    
    Another consideration is whether to address scenarios where tables are
    subsequently removed from the subscription, given that slots and origins would
    already have been created in such cases.
    
    Since it might introduce addition complexity to the patches, and considering
    that we already allow slot/origin to be created for empty subscription, it might
    also be acceptable to allow it to be created for sequence-only subscription. So,
    I chose to add some comments to explain the reason for it in latest version.
    
    Origin case might be slightly easier to handle, but it could also require some
    amount of implementations. Since origin is less harmful than a replication slot
    and maintaining it does not have noticeable overhead, it seems OK to me to
    retain the current behaviour and add some comments in the patch to clarify the
    same.
    
    Best Regards,
    Hou zj
    
  400. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-16T11:24:30Z

    On Tuesday, October 14, 2025 6:07 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > 
    > On Tue, Oct 14, 2025 at 3:33 PM Zhijie Hou (Fujitsu)
    > <houzj.fnst@fujitsu.com> wrote:
    > >
    > > 0003~0005:
    > > Unchanged.
    > >
    > > TODO:
    > > * The latest comment from Shveta[5].
    > > * The comment from Amit[6] to avoid creating slot/origin for sequence only
    > subscription.
    > >
    > 
    > Few comments on 0003 and 0004 based on previous version of the patch.
    > As those are not changed, so I assume they apply for the new version
    > as well.
    
    Thanks for the comments.
    
    > 
    > 2.
    > - /* Process any tables that are being synchronized in parallel. */
    > + /*
    > + * Process any tables that are being synchronized in parallel and any
    > + * newly added relations.
    > + */
    >   ProcessSyncingRelations(commit_data.end_lsn);
    > 
    >   pgstat_report_activity(STATE_IDLE, NULL);
    > @@ -1364,7 +1372,10 @@ apply_handle_prepare(StringInfo s)
    > 
    >   in_remote_transaction = false;
    > 
    > - /* Process any tables that are being synchronized in parallel. */
    > + /*
    > + * Process any tables that are being synchronized in parallel and any
    > + * newly added relations.
    > + */
    >   ProcessSyncingRelations(prepare_data.end_lsn);
    > 
    > In the first line of comment, it is mentioned as tables and in the
    > second line, the relations are mentioned. I think as part of this it
    > can process sequences as well if any are added. I wonder whether this
    > (while applying prepare/commit) is the right time to invoke it for
    > sequences. The apply worker do need to invoke sequencesync worker if
    > required but not sure if this is the right place.
    
    I agree that we can start sequence sync worker at any point regardless of the
    transaction boundary, because we do not support incremental seq sync, so another
    approach could be to call ProcessSyncingSequencesForApply() in the main loop of
    LogicalRepApplyLoop(), similar to maybe_advance_nonremovable_xid().
    
    OTOH, I think the current implementation also works, because we have one
    ProcessSyncingRelations() call in the main loop as well.
    
    What do you think ?
    
    > 
    > 4.
    > @@ -3284,7 +3307,7 @@ FindDeletedTupleInLocalRel(Relation localrel,
    > Oid localidxoid,
    >   */
    >   LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
    >   leader = logicalrep_worker_find(MyLogicalRepWorker->subid,
    > - InvalidOid, false);
    > + InvalidOid, false, false);
    > 
    > …
    >  extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
    > + LogicalRepWorkerType wtype,
    >   bool only_running);
    > 
    > The third parameter is LogicalRepWorkerType and passing it false in
    > the above usage doesn't make sense. Also, we should update comments
    > atop logicalrep_worker_find as to why worker_type is required. I want
    > to know why subid+relid combination is not sufficient to identify the
    > workers uniquely.
    
    I think it's because sequencesync worker also do not have a valid relid, similar
    to the apply worker, so we would need the worker type to distinguish them. I
    added some general comments atop of the function in the latest version.
    
    Best Regards,
    Hou zj
    
  401. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-17T04:23:53Z

    On Thu, Oct 16, 2025 at 4:54 PM Zhijie Hou (Fujitsu)
    <houzj.fnst@fujitsu.com> wrote:
    >
    > On Tuesday, October 14, 2025 6:07 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > 2.
    > > - /* Process any tables that are being synchronized in parallel. */
    > > + /*
    > > + * Process any tables that are being synchronized in parallel and any
    > > + * newly added relations.
    > > + */
    > >   ProcessSyncingRelations(commit_data.end_lsn);
    > >
    > >   pgstat_report_activity(STATE_IDLE, NULL);
    > > @@ -1364,7 +1372,10 @@ apply_handle_prepare(StringInfo s)
    > >
    > >   in_remote_transaction = false;
    > >
    > > - /* Process any tables that are being synchronized in parallel. */
    > > + /*
    > > + * Process any tables that are being synchronized in parallel and any
    > > + * newly added relations.
    > > + */
    > >   ProcessSyncingRelations(prepare_data.end_lsn);
    > >
    > > In the first line of comment, it is mentioned as tables and in the
    > > second line, the relations are mentioned. I think as part of this it
    > > can process sequences as well if any are added. I wonder whether this
    > > (while applying prepare/commit) is the right time to invoke it for
    > > sequences. The apply worker do need to invoke sequencesync worker if
    > > required but not sure if this is the right place.
    >
    > I agree that we can start sequence sync worker at any point regardless of the
    > transaction boundary, because we do not support incremental seq sync, so another
    > approach could be to call ProcessSyncingSequencesForApply() in the main loop of
    > LogicalRepApplyLoop(), similar to maybe_advance_nonremovable_xid().
    >
    > OTOH, I think the current implementation also works, because we have one
    > ProcessSyncingRelations() call in the main loop as well.
    >
    
    Yeah, the current implementation also appears good, but let's change
    the comment to: "Process any tables that are being synchronized in
    parallel, as well as any newly added tables or sequences."
    
    > What do you think ?
    >
    > >
    > > 4.
    > > @@ -3284,7 +3307,7 @@ FindDeletedTupleInLocalRel(Relation localrel,
    > > Oid localidxoid,
    > >   */
    > >   LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
    > >   leader = logicalrep_worker_find(MyLogicalRepWorker->subid,
    > > - InvalidOid, false);
    > > + InvalidOid, false, false);
    > >
    > > …
    > >  extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
    > > + LogicalRepWorkerType wtype,
    > >   bool only_running);
    > >
    > > The third parameter is LogicalRepWorkerType and passing it false in
    > > the above usage doesn't make sense. Also, we should update comments
    > > atop logicalrep_worker_find as to why worker_type is required. I want
    > > to know why subid+relid combination is not sufficient to identify the
    > > workers uniquely.
    >
    > I think it's because sequencesync worker also do not have a valid relid, similar
    > to the apply worker, so we would need the worker type to distinguish them. I
    > added some general comments atop of the function in the latest version.
    >
    
    Thanks, the added comments make the change easy to understand.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  402. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-17T04:31:42Z

    On Thu, Oct 16, 2025 at 4:53 PM Zhijie Hou (Fujitsu)
    <houzj.fnst@fujitsu.com> wrote:
    >
    > Regarding whether we can avoid creating slot/origin for seq-only publication.
    > I think the main challenge lies in ensuring the apply worker operates smoothly
    > without a replication slot. Currently, the apply worker uses the
    > START_REPLICATION command with a replication slot to acquire the slot on the
    > publisher. To bypass this, it's essential to skip starting the replication and
    > specifically, avoid entering the LogicalRepApplyLoop().
    >
    > To address this, I thought to implement a separate loop dedicated to
    > sequence-only subscriptions. Within this loop, the apply worker would only call
    > functions like ProcessSyncingSequencesForApply() to manage sequence
    > synchronization while periodically checking for any new tables added to the
    > subscription. If new tables are detected, the apply worker would exit this loop
    > and enter the LogicalRepApplyLoop().
    >
    > I chose not to consider allowing the START_REPLICATION command to operate
    > without a logical slot, as it seems like an unconventional approach requiring
    > modifications in walsender and to skip logical decoding and related processes.
    >
    > Another consideration is whether to address scenarios where tables are
    > subsequently removed from the subscription, given that slots and origins would
    > already have been created in such cases.
    >
    > Since it might introduce addition complexity to the patches, and considering
    > that we already allow slot/origin to be created for empty subscription, it might
    > also be acceptable to allow it to be created for sequence-only subscription. So,
    > I chose to add some comments to explain the reason for it in latest version.
    >
    > Origin case might be slightly easier to handle, but it could also require some
    > amount of implementations. Since origin is less harmful than a replication slot
    > and maintaining it does not have noticeable overhead, it seems OK to me to
    > retain the current behaviour and add some comments in the patch to clarify the
    > same.
    >
    
    I agree that avoiding to create a slot/origin for sequence-only
    subscription is not worth the additional complexity at other places,
    especially when we do create them for empty subscriptions.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  403. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-17T08:35:18Z

    On Fri, Oct 17, 2025 at 10:01 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Oct 16, 2025 at 4:53 PM Zhijie Hou (Fujitsu)
    > <houzj.fnst@fujitsu.com> wrote:
    > >
    > > Regarding whether we can avoid creating slot/origin for seq-only publication.
    > > I think the main challenge lies in ensuring the apply worker operates smoothly
    > > without a replication slot. Currently, the apply worker uses the
    > > START_REPLICATION command with a replication slot to acquire the slot on the
    > > publisher. To bypass this, it's essential to skip starting the replication and
    > > specifically, avoid entering the LogicalRepApplyLoop().
    > >
    > > To address this, I thought to implement a separate loop dedicated to
    > > sequence-only subscriptions. Within this loop, the apply worker would only call
    > > functions like ProcessSyncingSequencesForApply() to manage sequence
    > > synchronization while periodically checking for any new tables added to the
    > > subscription. If new tables are detected, the apply worker would exit this loop
    > > and enter the LogicalRepApplyLoop().
    > >
    > > I chose not to consider allowing the START_REPLICATION command to operate
    > > without a logical slot, as it seems like an unconventional approach requiring
    > > modifications in walsender and to skip logical decoding and related processes.
    > >
    > > Another consideration is whether to address scenarios where tables are
    > > subsequently removed from the subscription, given that slots and origins would
    > > already have been created in such cases.
    > >
    > > Since it might introduce addition complexity to the patches, and considering
    > > that we already allow slot/origin to be created for empty subscription, it might
    > > also be acceptable to allow it to be created for sequence-only subscription. So,
    > > I chose to add some comments to explain the reason for it in latest version.
    > >
    > > Origin case might be slightly easier to handle, but it could also require some
    > > amount of implementations. Since origin is less harmful than a replication slot
    > > and maintaining it does not have noticeable overhead, it seems OK to me to
    > > retain the current behaviour and add some comments in the patch to clarify the
    > > same.
    > >
    >
    > I agree that avoiding to create a slot/origin for sequence-only
    > subscription is not worth the additional complexity at other places,
    > especially when we do create them for empty subscriptions.
    
    +1.
    
    While testeing 001 patch alone, I found that for sequence-only
    subscription, we get error in tablesync worker :
    ERROR:  relation "public.seq1" type mismatch: source "table", target "sequence"
    
    This error comes because during copy_table(),
    logicalrep_relmap_update() does not update relkind and thus later
    CheckSubscriptionRelkind() ends up giving the above error.
    
    thanks
    Shveta
    
    
    
    
  404. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-17T08:50:21Z

    On Thu, Oct 16, 2025 at 4:53 PM Zhijie Hou (Fujitsu)
    <houzj.fnst@fujitsu.com> wrote:
    >
    > Thanks! Here is the remaining patches, which addressed all pending comments.
    >
    
    Few comments on 0001/0003:
    ========================
    1.
    @@ -480,7 +480,9 @@ RemoveSubscriptionRel(Oid subid, Oid relid)
      * leave tablesync slots or origins in the system when the
      * corresponding table is dropped.
      */
    - if (!OidIsValid(subid) && subrel->srsubstate != SUBREL_STATE_READY)
    + if (!OidIsValid(subid) &&
    + get_rel_relkind(subrel->srrelid) != RELKIND_SEQUENCE &&
    + subrel->srsubstate != SUBREL_STATE_READY)
      {
    
    Here, why don't we allow sequence rel to be removed? Please add some comments.
    
    2.
    /*
      * Get the relations for the subscription.
      *
    - * If not_ready is true, return only the relations that are not in a ready
    - * state, otherwise return all the relations of the subscription.  The
    - * returned list is palloc'ed in the current memory context.
    + * get_tables: get relations for tables of the subscription.
    + *
    + * get_sequences: get relations for sequences of the subscription.
    + *
    + * not_ready:
    + * If getting tables and not_ready is false, retrieve all tables;
    + * otherwise, retrieve only tables that have not reached the READY state.
    + * If getting sequences and not_ready is false, retrieve all sequences;
    + * otherwise, retrieve only sequences that have not reached the READY state.
    + *
    + * The returned list is palloc'ed in the current memory context.
      */
     List *
    -GetSubscriptionRelations(Oid subid, bool not_ready)
    +GetSubscriptionRelations(Oid subid, bool get_tables, bool get_sequences,
    + bool not_ready)
    
    The existing code comments (without the patch) are good enough for this change.
    
    3. Move catalogs.sgml, alter_subscription.sgml (parts related to 0001)
    from 0003 to 0001. Also, see if anything else can be moved.
    
    4.
          <para>
    -      Fetch missing table information from publisher.  This will start
    +      Fetch missing table information from the publisher.  This will start
           replication of tables that were added to the subscribed-to publications
           since <link linkend="sql-createsubscription">
           <command>CREATE SUBSCRIPTION</command></link> or
           the last invocation of <command>REFRESH PUBLICATION</command>.
          </para>
    
    +     <para>
    +      Also, fetch missing sequence information from the publisher.
    +     </para>
    
    The second para should be merged into the first one: Fetch missing
    table and sequence information from the publisher.
    
    5.
    +      </para>
    +      <para>
    +       State codes for sequences:
    +       <literal>i</literal> = initialize,
    +       <literal>d</literal> = re-synchronize,
    +       <literal>r</literal> = ready
    </para></entry>
    
    I think we need to remove the 'd' state from here as the patch 0001
    changes always update the sequence state to init.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  405. Re: Logical Replication of sequences

    Chao Li <li.evan.chao@gmail.com> — 2025-10-17T09:34:16Z

    I just reviewed 0001 and got a few comments wrt code comments. I may find some time to review 0002 and 0003 next week.
    
    > On Oct 16, 2025, at 19:23, Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> wrote:
    > 
    > <v20251016-0003-Documentation-for-sequence-synchronization.patch><v20251016-0002-New-worker-for-sequence-synchronization-du.patch><v20251016-0001-Introduce-REFRESH-SEQUENCES-for-subscripti.patch>
    
    1 - 0001 - pg_subscription.c
    ```
    +		/*
    +		 * Skip sequence tuples. If even a single table tuple exists then the
    +		 * subscription has tables.
    +		 */
    +		if (get_rel_relkind(subrel->srrelid) == RELKIND_RELATION ||
    +			get_rel_relkind(subrel->srrelid) == RELKIND_PARTITIONED_TABLE)
    +		{
    +			has_subrels = true;
    +			break;
    +		}
    ```
    
    The comment "If even a single table tuple exists then the subscription has tables” sounds redundant. I know it’s inherited from the old code, but now, with the “break” you newly added, the code logic is simple and clear, so I think the comment is no longer needed.
    
    2 - 0001  - pg_subscription.c
    ```
    @@ -542,12 +560,21 @@ HasSubscriptionTables(Oid subid)
    + * get_tables: get relations for tables of the subscription.
    + *
    + * get_sequences: get relations for sequences of the subscription.
    + *
    + * not_ready:
    + * If getting tables and not_ready is false, retrieve all tables;
    + * otherwise, retrieve only tables that have not reached the READY state.
    + * If getting sequences and not_ready is false, retrieve all sequences;
    + * otherwise, retrieve only sequences that have not reached the READY state.
    + *
    ```
    
    This function comment sounds a bit verbose and repetitive. Suggested revision:
    ```
    * get_tables: if true, include tables in the returned list.
     * get_sequences: if true, include sequences in the returned list.
     * not_ready: if true, include only objects that have not reached the READY state;
     *            if false, include all objects of the requested type(s).
    ```
    
    3 - 0001 - subscriptioncmds.c
    ```
    +			 * Currently, a replication slot is created for all subscriptions,
    +			 * including those for empty or sequence-only publications. While
    +			 * this is unnecessary, optimizing this behavior would require
    +			 * additional handling to ensure the apply worker operates
    +			 * smoothly without acquiring a slot on the publisher, thus adding
    +			 * complexity to the apply worker. Given that such subscriptions
    +			 * are infrequent, it doesn't seem to be worth doing anything
    +			 * about it.
    ```
    
    Minor tweaks:
    * "optimizing this behavior” -> “optimizing it”
    * “doing anything about it” -> “addressing it"
    
    4 - 0001 - subscriptioncmds.c
    ```
     * 3) For ALTER SUBSCRIPTION ... REFRESH SEQUENCE statements with "copy_data =
    * true" and "origin = none":
    * - Warn the user that sequence data from another origin might have been
    * copied.
    ```
    
    “Warn the user” -> “Warn users"
    
    Best regards,
    --
    Chao Li (Evan)
    HighGo Software Co., Ltd.
    https://www.highgo.com/
    
    
    
    
    
    
    
    
  406. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-17T10:27:05Z

    On Thu, Oct 16, 2025 at 4:53 PM Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com>
    wrote:
    
    > On Thursday, October 16, 2025 5:59 PM Amit Kapila <amit.kapila16@gmail.com>
    > wrote:
    > >
    >
    
    While reading through the patch, I have 2 comments in 0002
    
    1.
    + ereport(LOG,
    + errmsg("logical replication sequence synchronization for subscription
    \"%s\" - batch #%d = %d attempted, %d succeeded, %d skipped, %d mismatched,
    %d insufficient permission, %d missing, ",
    +   MySubscription->name, (current_index / MAX_SEQUENCES_SYNC_PER_BATCH) +
    1, batch_size,
    +   batch_succeeded_count, batch_skipped_count, batch_mismatched_count,
    batch_insuffperm_count,
    +   batch_size - (batch_succeeded_count + batch_skipped_count +
    batch_mismatched_count + batch_insuffperm_count)));
    +
    
     The log message is ending with ..." %d missing, "  (a trailing comma and
    space).
    
    2.
    Also IMHO instead of just saying "missing" we can say "missing on/from
    publisher" so that it would be more clear.
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
  407. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-17T19:44:09Z

    On Fri, Oct 17, 2025 at 1:35 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Fri, Oct 17, 2025 at 10:01 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Thu, Oct 16, 2025 at 4:53 PM Zhijie Hou (Fujitsu)
    > > <houzj.fnst@fujitsu.com> wrote:
    > > >
    > > > Regarding whether we can avoid creating slot/origin for seq-only publication.
    > > > I think the main challenge lies in ensuring the apply worker operates smoothly
    > > > without a replication slot. Currently, the apply worker uses the
    > > > START_REPLICATION command with a replication slot to acquire the slot on the
    > > > publisher. To bypass this, it's essential to skip starting the replication and
    > > > specifically, avoid entering the LogicalRepApplyLoop().
    > > >
    > > > To address this, I thought to implement a separate loop dedicated to
    > > > sequence-only subscriptions. Within this loop, the apply worker would only call
    > > > functions like ProcessSyncingSequencesForApply() to manage sequence
    > > > synchronization while periodically checking for any new tables added to the
    > > > subscription. If new tables are detected, the apply worker would exit this loop
    > > > and enter the LogicalRepApplyLoop().
    > > >
    > > > I chose not to consider allowing the START_REPLICATION command to operate
    > > > without a logical slot, as it seems like an unconventional approach requiring
    > > > modifications in walsender and to skip logical decoding and related processes.
    > > >
    > > > Another consideration is whether to address scenarios where tables are
    > > > subsequently removed from the subscription, given that slots and origins would
    > > > already have been created in such cases.
    > > >
    > > > Since it might introduce addition complexity to the patches, and considering
    > > > that we already allow slot/origin to be created for empty subscription, it might
    > > > also be acceptable to allow it to be created for sequence-only subscription. So,
    > > > I chose to add some comments to explain the reason for it in latest version.
    > > >
    > > > Origin case might be slightly easier to handle, but it could also require some
    > > > amount of implementations. Since origin is less harmful than a replication slot
    > > > and maintaining it does not have noticeable overhead, it seems OK to me to
    > > > retain the current behaviour and add some comments in the patch to clarify the
    > > > same.
    > > >
    > >
    > > I agree that avoiding to create a slot/origin for sequence-only
    > > subscription is not worth the additional complexity at other places,
    > > especially when we do create them for empty subscriptions.
    >
    > +1.
    >
    > While testeing 001 patch alone, I found that for sequence-only
    > subscription, we get error in tablesync worker :
    > ERROR:  relation "public.seq1" type mismatch: source "table", target "sequence"
    >
    > This error comes because during copy_table(),
    > logicalrep_relmap_update() does not update relkind and thus later
    > CheckSubscriptionRelkind() ends up giving the above error.
    
    I faced the same error while reviewing the 0001 patch. I think if
    we're going to push these patches separately the 0001 patch should
    have at least minimal regression tests. Otherwise, I'm concerned that
    buildfarm animals won't complain but we could end up blocking other
    logical replication developments.
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  408. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-18T01:24:26Z

    On Fri, Oct 17, 2025 at 12:44 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Fri, Oct 17, 2025 at 1:35 AM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Fri, Oct 17, 2025 at 10:01 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Thu, Oct 16, 2025 at 4:53 PM Zhijie Hou (Fujitsu)
    > > > <houzj.fnst@fujitsu.com> wrote:
    > > > >
    > > > > Regarding whether we can avoid creating slot/origin for seq-only publication.
    > > > > I think the main challenge lies in ensuring the apply worker operates smoothly
    > > > > without a replication slot. Currently, the apply worker uses the
    > > > > START_REPLICATION command with a replication slot to acquire the slot on the
    > > > > publisher. To bypass this, it's essential to skip starting the replication and
    > > > > specifically, avoid entering the LogicalRepApplyLoop().
    > > > >
    > > > > To address this, I thought to implement a separate loop dedicated to
    > > > > sequence-only subscriptions. Within this loop, the apply worker would only call
    > > > > functions like ProcessSyncingSequencesForApply() to manage sequence
    > > > > synchronization while periodically checking for any new tables added to the
    > > > > subscription. If new tables are detected, the apply worker would exit this loop
    > > > > and enter the LogicalRepApplyLoop().
    > > > >
    > > > > I chose not to consider allowing the START_REPLICATION command to operate
    > > > > without a logical slot, as it seems like an unconventional approach requiring
    > > > > modifications in walsender and to skip logical decoding and related processes.
    > > > >
    > > > > Another consideration is whether to address scenarios where tables are
    > > > > subsequently removed from the subscription, given that slots and origins would
    > > > > already have been created in such cases.
    > > > >
    > > > > Since it might introduce addition complexity to the patches, and considering
    > > > > that we already allow slot/origin to be created for empty subscription, it might
    > > > > also be acceptable to allow it to be created for sequence-only subscription. So,
    > > > > I chose to add some comments to explain the reason for it in latest version.
    > > > >
    > > > > Origin case might be slightly easier to handle, but it could also require some
    > > > > amount of implementations. Since origin is less harmful than a replication slot
    > > > > and maintaining it does not have noticeable overhead, it seems OK to me to
    > > > > retain the current behaviour and add some comments in the patch to clarify the
    > > > > same.
    > > > >
    > > >
    > > > I agree that avoiding to create a slot/origin for sequence-only
    > > > subscription is not worth the additional complexity at other places,
    > > > especially when we do create them for empty subscriptions.
    > >
    > > +1.
    > >
    > > While testeing 001 patch alone, I found that for sequence-only
    > > subscription, we get error in tablesync worker :
    > > ERROR:  relation "public.seq1" type mismatch: source "table", target "sequence"
    > >
    > > This error comes because during copy_table(),
    > > logicalrep_relmap_update() does not update relkind and thus later
    > > CheckSubscriptionRelkind() ends up giving the above error.
    >
    > I faced the same error while reviewing the 0001 patch. I think if
    > we're going to push these patches separately the 0001 patch should
    > have at least minimal regression tests. Otherwise, I'm concerned that
    > buildfarm animals won't complain but we could end up blocking other
    > logical replication developments.
    >
    
    One minor comment for 0001 patch is:
    
    +       /*
    +        * Skip sequence tuples. If even a single table tuple exists then the
    +        * subscription has tables.
    +        */
    +       if (get_rel_relkind(subrel->srrelid) == RELKIND_RELATION ||
    +           get_rel_relkind(subrel->srrelid) == RELKIND_PARTITIONED_TABLE)
    +       {
    +           has_subrels = true;
    +           break;
    +       }
    
    How about storing the relkind to a variable here and avoiding calling
    get_rel_relkind() twice (to save one syscache lookup)?
    
    Regards,
    
    -- 
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  409. Re: Logical Replication of sequences

    Chao Li <li.evan.chao@gmail.com> — 2025-10-20T02:52:40Z

    
    > On Oct 17, 2025, at 17:34, Chao Li <li.evan.chao@gmail.com> wrote:
    > 
    > I may find some time to review 0002 and 0003 next week.
    
    I just reviewed 0002 and 0003. Got some comments for 0002, and no comment for 0003.
    
    
    1 - 0002 - commit comment
    ```
    Sequences have 3 states:
       - INIT (needs [re]synchronizing)
       - READY (is already synchronized)
    ```
    
    3 states or 2 states? Missing DATASYNC?
    
    
    2 - 0002 - launcher.c
    ```
    + * For both apply workers and sequence sync workers, the relid should be set to
    + * InvalidOid, as they manage changes across all tables and sequences. For table
    + * sync workers, the relid should be set to the OID of the relation being
    + * synchronized.
    ```
    
    Nit: “both” sounds not necessarily.
    
    3 - 0002 - launcher.c
    ```
      * Stop the logical replication worker for subid/relid, if any.
      */
     void
    -logicalrep_worker_stop(Oid subid, Oid relid)
    +logicalrep_worker_stop(Oid subid, Oid relid, LogicalRepWorkerType wtype)
    ```
    
    Should the comment be updated? “subid/relid/wtype"
    
    4 - 0002 - launcher.c
    ```
    -	worker = logicalrep_worker_find(subid, relid, true);
    +	worker = logicalrep_worker_find(subid, relid, WORKERTYPE_APPLY, true);
    ```
    
    Based the comment you added to “logicalrep_worker_find()”, for apply worker, relid should be set to InvalidOid. (See comment 2)
    
    Then if you change this function to only work for WORKERTYPE_APPLY, relid should be hard code to InvalidOid, so that “relid” can be removed from parameter list of logicalrep_worker_wakeup().
    
    5 - 0002 - launcher.c
    ```
    /*
    * report_error_sequences
    *
    * Reports discrepancies in sequence data between the publisher and subscriber.
    ```
    
    Nit: “Reports” -> “Report”
    
    Here “reports” also work. But looking at the previous function’s comment:
    
    ```
     * Handle sequence synchronization cooperation from the apply worker.
    *
    * Start a sequencesync worker if one is not already running. The active
    ```
    
    You used “handle” and “start” but “handles” and “starts”.
    
    “Report” better matches imperative style in PG comments.
    
    6 - 0002 - sequencesync.c
    ```
    +report_error_sequences(StringInfo insuffperm_seqs, StringInfo mismatched_seqs)
    +{
    +	StringInfo	combined_error_detail = makeStringInfo();
    +	StringInfo	combined_error_hint = makeStringInfo();
    ```
    
    By the end of this function, I think we need to destroyStringInfo() these two strings.
    
    7 - 0002 - sequencesync.c
    ```
    +static void
    +append_sequence_name(StringInfo buf, const char *nspname, const char *seqname,
    +					 int *count)
    +{
    +	if (buf->len > 0)
    +		appendStringInfoString(buf, ", “);
    ```
    
    Why this “if” check is needed?
    
    8 - 0002 - sequencesync.c 
    ```
    +		destroyStringInfo(seqstr);
    +		destroyStringInfo(cmd);
    ```
    
    Instead of making and destroying seqstr and cmd in every iteration, we can create them before “while”, and only resetStringInfo() them for every iteration, which should be cheaper and faster.
    
    9 - 0002 - sequencesync.c
    ```
    +	return h1 ^ h2;
    +	/* XOR combine */
    +}
    ```
    
    This code is very descriptive, so the commend looks redundant. Also, why put the comment below the code line?
    
    10 - 0002 - syncutils.c
    ```
     /*
    - * Common code to fetch the up-to-date sync state info into the static lists.
    + * Common code to fetch the up-to-date sync state info for tables and sequences.
      *
    - * Returns true if subscription has 1 or more tables, else false.
    + * The pg_subscription_rel catalog is shared by tables and sequences. Changes
    + * to either sequences or tables can affect the validity of relation states, so
    + * we identify non-ready tables and non-ready sequences together to ensure
    + * consistency.
      *
    - * Note: If this function started the transaction (indicated by the parameter)
    - * then it is the caller's responsibility to commit it.
    + * Returns true if subscription has 1 or more tables, else false.
      */
     bool
    -FetchRelationStates(bool *started_tx)
    +FetchRelationStates(bool *has_pending_sequences, bool *started_tx)
    ```
    has_pending_sequences is not explained in the function comment.
    
    11 - 0002 - syncutils.c
    ```
        /*
    * has_subtables and has_subsequences is declared as static, since the
    * same value can be used until the system table is invalidated.
    */
    static bool has_subtables = false;
    static bool has_subsequences_non_ready = false;
    ```
    
    The comment says “has_subsequences”, but the real var name is “has_subsequences_non_ready".
    
    12 - 0002 - syncutils.c
    ```
     bool
    -FetchRelationStates(bool *started_tx)
    +FetchRelationStates(bool *has_pending_sequences, bool *started_tx)
    ```
    
    I searched over the code, this function has 3 callers, none of them want results for both table and sequence, so that a caller, for example:
    
    ```
    bool
    HasSubscriptionTablesCached(void)
    {
    bool started_tx;
    bool has_subrels;
    bool has_pending_sequences;
    
    /* We need up-to-date subscription tables info here */
    has_subrels = FetchRelationStates(&has_pending_sequences, &started_tx);
    
    if (started_tx)
    {
    CommitTransactionCommand();
    pgstat_report_stat(true);
    }
    
    return has_subrels;
    }
    ```
    
    Looks confused because it defines has_pending_sequences but not using it at all.
    
    So, I think FetchRelationStates() can be refactored to return a result for either table or sequence, because on a type parameter.
    
    Best regards,
    --
    Chao Li (Evan)
    HighGo Software Co., Ltd.
    https://www.highgo.com/
    
    
    
    
    
    
    
    
  410. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-20T09:31:06Z

    On Friday, October 17, 2025 4:50 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > 
    > On Thu, Oct 16, 2025 at 4:53 PM Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com>
    > wrote:
    > >
    > > Thanks! Here is the remaining patches, which addressed all pending
    > comments.
    > >
    > 
    > Few comments on 0001/0003:
    
    Thanks for the comments.
    
    > ========================
    > 1.
    > @@ -480,7 +480,9 @@ RemoveSubscriptionRel(Oid subid, Oid relid)
    >   * leave tablesync slots or origins in the system when the
    >   * corresponding table is dropped.
    >   */
    > - if (!OidIsValid(subid) && subrel->srsubstate != SUBREL_STATE_READY)
    > + if (!OidIsValid(subid) &&
    > + get_rel_relkind(subrel->srrelid) != RELKIND_SEQUENCE &&
    > + subrel->srsubstate != SUBREL_STATE_READY)
    >   {
    > 
    > Here, why don't we allow sequence rel to be removed? Please add some
    > comments.
    
    I think the intention is to allow removing sequence because we do not
    create slot/origin when syncing sequence. I added some comments
    for the same.
    
    Other comments have been addressed in latest version.
    
    Here is the latest patch set which addressed Shveta[1], Amit[2], Chao[3][4],
    Dilip[5], Sawada-San's[6] comments.
    
    Some of the code refactoring comments in [4] will be considered in
    next versions.
    
    [1] https://www.postgresql.org/message-id/CAJpy0uC898ga%2BQo3X%3Dk_MaRUL7EnmXt%2BppDJo-nroQZifrk5Hw%40mail.gmail.com
    [2] https://www.postgresql.org/message-id/CAA4eK1K6Aofz_f6afuL%2Br2M3GfHBEYQ6-5JO93ph9xZAmYugSA%40mail.gmail.com
    [3] https://www.postgresql.org/message-id/B0F583F9-6D4D-4C0F-9F35-64D5AB2F1643%40gmail.com
    [4] https://www.postgresql.org/message-id/598FC353-8E9A-4857-A125-740BE24DCBEB%40gmail.com
    [5] https://www.postgresql.org/message-id/CAFiTN-sC4yE_u7fa%2BUQS38JvhxN_VYSWTq2O_2bTRxxq%3DeW8FQ%40mail.gmail.com
    [6] https://www.postgresql.org/message-id/CAD21AoBYP1a4%2B%2BALRPG%3DSmCoyGeGCcqhFxWSXYhy1cvmN0i3CA%40mail.gmail.com
    
    Best Regards,
    Hou zj
    
    
  411. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-20T09:31:13Z

    On Saturday, October 18, 2025 3:44 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > 
    > On Fri, Oct 17, 2025 at 1:35 AM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Fri, Oct 17, 2025 at 10:01 AM Amit Kapila <amit.kapila16@gmail.com>
    > wrote:
    > > >
    > > > On Thu, Oct 16, 2025 at 4:53 PM Zhijie Hou (Fujitsu)
    > > > <houzj.fnst@fujitsu.com> wrote:
    > > > >
    > > > > Regarding whether we can avoid creating slot/origin for seq-only
    > publication.
    > > > > I think the main challenge lies in ensuring the apply worker
    > > > > operates smoothly without a replication slot. Currently, the apply
    > > > > worker uses the START_REPLICATION command with a replication slot
    > > > > to acquire the slot on the publisher. To bypass this, it's
    > > > > essential to skip starting the replication and specifically, avoid entering
    > the LogicalRepApplyLoop().
    > > > >
    > > > > To address this, I thought to implement a separate loop dedicated
    > > > > to sequence-only subscriptions. Within this loop, the apply worker
    > > > > would only call functions like ProcessSyncingSequencesForApply()
    > > > > to manage sequence synchronization while periodically checking for
    > > > > any new tables added to the subscription. If new tables are
    > > > > detected, the apply worker would exit this loop and enter the
    > LogicalRepApplyLoop().
    > > > >
    > > > > I chose not to consider allowing the START_REPLICATION command to
    > > > > operate without a logical slot, as it seems like an unconventional
    > > > > approach requiring modifications in walsender and to skip logical
    > decoding and related processes.
    > > > >
    > > > > Another consideration is whether to address scenarios where tables
    > > > > are subsequently removed from the subscription, given that slots
    > > > > and origins would already have been created in such cases.
    > > > >
    > > > > Since it might introduce addition complexity to the patches, and
    > > > > considering that we already allow slot/origin to be created for
    > > > > empty subscription, it might also be acceptable to allow it to be
    > > > > created for sequence-only subscription. So, I chose to add some
    > comments to explain the reason for it in latest version.
    > > > >
    > > > > Origin case might be slightly easier to handle, but it could also
    > > > > require some amount of implementations. Since origin is less
    > > > > harmful than a replication slot and maintaining it does not have
    > > > > noticeable overhead, it seems OK to me to retain the current
    > > > > behaviour and add some comments in the patch to clarify the same.
    > > > >
    > > >
    > > > I agree that avoiding to create a slot/origin for sequence-only
    > > > subscription is not worth the additional complexity at other places,
    > > > especially when we do create them for empty subscriptions.
    > >
    > > +1.
    > >
    > > While testeing 001 patch alone, I found that for sequence-only
    > > subscription, we get error in tablesync worker :
    > > ERROR:  relation "public.seq1" type mismatch: source "table", target
    > "sequence"
    > >
    > > This error comes because during copy_table(),
    > > logicalrep_relmap_update() does not update relkind and thus later
    > > CheckSubscriptionRelkind() ends up giving the above error.
    
    Fixed in latest version.
    
    > 
    > I faced the same error while reviewing the 0001 patch. I think if we're going to
    > push these patches separately the 0001 patch should have at least minimal
    > regression tests. Otherwise, I'm concerned that buildfarm animals won't
    > complain but we could end up blocking other logical replication developments.
    
    I moved some test from 0002 to 0001. Thanks Kuroda-San for contributing
    codes for this change.
    
    Best Regards,
    Hou zj
    
  412. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-20T09:32:12Z

    On Monday, October 20, 2025 10:53 AM Chao Li <li.evan.chao@gmail.com> wrote:
    > 
    > > On Oct 17, 2025, at 17:34, Chao Li <li.evan.chao@gmail.com> wrote:
    > >
    > > I may find some time to review 0002 and 0003 next week.
    
    Thanks for the comments.
    
    > > 
    > > 2 - 0001  - pg_subscription.c
    > > ```
    > > @@ -542,12 +560,21 @@ HasSubscriptionTables(Oid subid)
    > > + * get_tables: get relations for tables of the subscription.
    > > + *
    > > + * get_sequences: get relations for sequences of the subscription.
    > > + *
    > > + * not_ready:
    > > + * If getting tables and not_ready is false, retrieve all tables;
    > > + * otherwise, retrieve only tables that have not reached the READY state.
    > > + * If getting sequences and not_ready is false, retrieve all sequences;
    > > + * otherwise, retrieve only sequences that have not reached the READY state.
    > > + *
    > > ```
    > > 
    > > This function comment sounds a bit verbose and repetitive. Suggested
    > > revision:
    > > ```
    > > * get_tables: if true, include tables in the returned list.
    > >  * get_sequences: if true, include sequences in the returned list.
    > >  * not_ready: if true, include only objects that have not reached the READY
    > > state;
    > >  *            if false, include all objects of the requested type(s).
    > > ```
    
    I have reverted this change according to Amit's suggestion because
    existing comments is good enough.
    
    > > 
    > > 3 - 0001 - subscriptioncmds.c
    > > ```
    > > +			 * Currently, a replication slot is created for all
    > > subscriptions,
    > > +			 * including those for empty or sequence-only
    > > publications. While
    > > +			 * this is unnecessary, optimizing this behavior would
    > > ```
    > > 
    > > Minor tweaks:
    > > * "optimizing this behavior” -> “optimizing it”
    > > * “doing anything about it” -> “addressing it"
    
    I have re-rewritten this part as well based on some off-list
    discussions.
    
    > > 
    > > 4 - 0001 - subscriptioncmds.c
    > > ```
    > >  * 3) For ALTER SUBSCRIPTION ... REFRESH SEQUENCE statements with
    > > "copy_data =
    > > * true" and "origin = none":
    > > * - Warn the user that sequence data from another origin might have been
    > > * copied.
    > > ```
    > > 
    > > “Warn the user” -> “Warn users"
    
    I prefer to keep current word as that's the existing style used atop
    of check_publications_origin().
    
    > 
    > I just reviewed 0002 and 0003. Got some comments for 0002, and no comment
    > for 0003.
    > 
    > 4 - 0002 - launcher.c
    > ```
    > -	worker = logicalrep_worker_find(subid, relid, true);
    > +	worker = logicalrep_worker_find(subid, relid, WORKERTYPE_APPLY,
    > true);
    > ```
    > 
    > Based the comment you added to “logicalrep_worker_find()”, for apply worker,
    > relid should be set to InvalidOid. (See comment 2)
    > 
    > Then if you change this function to only work for WORKERTYPE_APPLY, relid
    > should be hard code to InvalidOid, so that “relid” can be removed from
    > parameter list of logicalrep_worker_wakeup().
    
    I chose to pass different worker type based on the passed OID in this version.
    If we decided to change the function interface to allow only apply worker, then
    we can change in later version.
    
    > 6 - 0002 - sequencesync.c
    > ```
    > +report_error_sequences(StringInfo insuffperm_seqs, StringInfo
    > mismatched_seqs)
    > +{
    > +	StringInfo	combined_error_detail = makeStringInfo();
    > +	StringInfo	combined_error_hint = makeStringInfo();
    > ```
    > 
    > By the end of this function, I think we need to destroyStringInfo() these two
    > strings.
    
    I think we do not need to free these strings as the worker will stop soon after
    executing this function. Similarly, some other string/hash table memory free
    in copy_sequences() and LogicalRepSyncSequences() also look unnecessary to me,
    and I will consider removing them in later version.
    
    > 
    > 7 - 0002 - sequencesync.c
    > ```
    > +static void
    > +append_sequence_name(StringInfo buf, const char *nspname, const char
    > *seqname,
    > +					 int *count)
    > +{
    > +	if (buf->len > 0)
    > +		appendStringInfoString(buf, ", “);
    > ```
    > 
    > Why this “if” check is needed?
    
    I think we want to append comma only when one sequence name
    has already been appended to the buf.
    
    > 
    > 10 - 0002 - syncutils.c
    > ```
    >  /*
    > - * Common code to fetch the up-to-date sync state info into the static lists.
    > + * Common code to fetch the up-to-date sync state info for tables and
    > sequences.
    >   *
    > - * Returns true if subscription has 1 or more tables, else false.
    > + * The pg_subscription_rel catalog is shared by tables and sequences.
    > Changes
    > + * to either sequences or tables can affect the validity of relation states, so
    > + * we identify non-ready tables and non-ready sequences together to ensure
    > + * consistency.
    >   *
    > - * Note: If this function started the transaction (indicated by the parameter)
    > - * then it is the caller's responsibility to commit it.
    > + * Returns true if subscription has 1 or more tables, else false.
    >   */
    >  bool
    > -FetchRelationStates(bool *started_tx)
    > +FetchRelationStates(bool *has_pending_sequences, bool *started_tx)
    > ```
    > has_pending_sequences is not explained in the function comment.
    > 
    > 11 - 0002 - syncutils.c
    > ```
    >     /*
    > * has_subtables and has_subsequences is declared as static, since the
    > * same value can be used until the system table is invalidated.
    > */
    > static bool has_subtables = false;
    > static bool has_subsequences_non_ready = false;
    > ```
    > 
    > The comment says “has_subsequences”, but the real var name is
    > “has_subsequences_non_ready".
    > 
    > 12 - 0002 - syncutils.c
    > ```
    >  bool
    > -FetchRelationStates(bool *started_tx)
    > +FetchRelationStates(bool *has_pending_sequences, bool *started_tx)
    > ```
    > 
    > I searched over the code, this function has 3 callers, none of them want results
    > for both table and sequence, so that a caller, for example:
    > 
    > ```
    > bool
    > HasSubscriptionTablesCached(void)
    > {
    > bool started_tx;
    > bool has_subrels;
    > bool has_pending_sequences;
    > 
    > /* We need up-to-date subscription tables info here */
    > has_subrels = FetchRelationStates(&has_pending_sequences, &started_tx);
    > 
    > if (started_tx)
    > {
    > CommitTransactionCommand();
    > pgstat_report_stat(true);
    > }
    > 
    > return has_subrels;
    > }
    > ```
    > 
    > Looks confused because it defines has_pending_sequences but not using it at
    > all.
    > 
    > So, I think FetchRelationStates() can be refactored to return a result for either
    > table or sequence, because on a type parameter.
    
    I will think more for this function and change in next version.
    
    Best Regards,
    Hou zj
    
  413. RE: Logical Replication of sequences

    Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-10-20T11:59:30Z

    > Here is the latest patch set which addressed Shveta[1], Amit[2], Chao[3][4],
    > Dilip[5], Sawada-San's[6] comments.
    
    I found the patch could not pass the sanity check, because 0001 missed a comma.
    Also, there was a duplicated entry for `REFRESH SEQUENCES`.
    
    Attached set fixed the issue.
    
    Best regards,
    Hayato Kuroda
    FUJITSU LIMITED 
    
    
  414. Re: Logical Replication of sequences

    Masahiko Sawada <sawada.mshk@gmail.com> — 2025-10-20T22:18:50Z

    On Mon, Oct 20, 2025 at 4:59 AM Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > > Here is the latest patch set which addressed Shveta[1], Amit[2], Chao[3][4],
    > > Dilip[5], Sawada-San's[6] comments.
    >
    > I found the patch could not pass the sanity check, because 0001 missed a comma.
    > Also, there was a duplicated entry for `REFRESH SEQUENCES`.
    >
    > Attached set fixed the issue.
    >
    
    Thank you for updating the patch! I have a few comments on the 0001 patch:
    
    -       appendStringInfo(&cmd, "SELECT DISTINCT n.nspname, c.relname,
    gpt.attrs\n"
    -                        "       FROM pg_class c\n"
    +       appendStringInfo(&cmd, "SELECT DISTINCT n.nspname, c.relname,
    gpt.attrs");
    +
    +       if (support_relkind_seq)
    +           appendStringInfo(&cmd, ", c.relkind\n");
    +
    +       appendStringInfo(&cmd, "   FROM pg_class c\n"
                             "         JOIN pg_namespace n ON n.oid =
    c.relnamespace\n"
                             "         JOIN ( SELECT
    (pg_get_publication_tables(VARIADIC array_agg(pubname::text))).*\n"
                             "                FROM pg_publication\n"
                             "                WHERE pubname IN ( %s )) AS gpt\n"
                             "             ON gpt.relid = c.oid\n",
                             pub_names->data);
    
    I think we don't necessarily need to avoid getting relkind for servers
    older than 19. IIUC the reason why we had to have check_columnlist was
    that the attnames column was introduced to pg_publication_tables
    catalog. But I think this patch is not the case since we get relkind
    from pg_class. That is, I think we can get 4 columns from server >=16.
    
    ---
     /*
    - * Check and log a warning if the publisher has subscribed to the same table,
    - * its partition ancestors (if it's a partition), or its partition children (if
    - * it's a partitioned table), from some other publishers. This check is
    - * required in the following scenarios:
    + * Check and log a warning if the publisher has subscribed to the same relation
    + * (table or sequence), its partition ancestors (if it's a partition), or its
    + * partition children (if it's a partitioned table), from some other
    publishers.
    + * This check is required in the following scenarios:
      *
      * 1) For CREATE SUBSCRIPTION and ALTER SUBSCRIPTION ... REFRESH PUBLICATION
      *    statements with "copy_data = true" and "origin = none":
      *    - Warn the user that data with an origin might have been copied.
    - *    - This check is skipped for tables already added, as incremental sync via
    - *      WAL allows origin tracking. The list of such tables is in
    - *      subrel_local_oids.
    + *    - This check is skipped for tables and sequences already added, as
    + *      incremental sync via WAL allows origin tracking. The list of
    such tables
    + *      is in subrel_local_oids.
      *
      * 2) For CREATE SUBSCRIPTION and ALTER SUBSCRIPTION ... REFRESH PUBLICATION
      *    statements with "retain_dead_tuples = true" and "origin = any", and for
    @@ -2338,13 +2440,19 @@ AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
      *    - Warn the user that only conflict detection info for local changes on
      *      the publisher is retained. Data from other origins may lack sufficient
      *      details for reliable conflict detection.
    + *    - This check targets for tables only.
      *    - See comments atop worker.c for more details.
    + *
    + * 3) For ALTER SUBSCRIPTION ... REFRESH SEQUENCE statements with "origin =
    + *    none":
    + *    - Warn the user that sequence data from another origin might have been
    + *      copied.
      */
    
    While this function is well documented, I find it's quite complex, and
    this patch adds to that complexity. The function has 9 arguments,
    making it difficult to understand which combinations of arguments
    enable which checks. For example, the function header comment doesn't
    explain when to use the only_sequences parameter. At first, I thought
    only_sequences should be set to true when checking if the publisher
    has subscribed to sequences from other publishers, but looking at the
    code, I discovered it doesn't check sequences when check_rdt is true:
    
    +   if (walrcv_server_version(wrconn) < 190000 || check_rdt)
    +       appendStringInfo(&cmd, query,
    +                        "(SELECT relid, TRUE as istable FROM
    pg_get_publication_tables(P.pubname))");
    +   else if (only_sequences)
    +       appendStringInfo(&cmd, query,
    +                        "(SELECT relid, FALSE as istable FROM
    pg_get_publication_sequences(P.pubname))");
    +   else
    +       appendStringInfo(&cmd, query,
    +                        "(SELECT relid, TRUE as istable FROM
    pg_get_publication_tables(P.pubname) UNION ALL"
    +                        " SELECT relid, FALSE as istable FROM
    pg_get_publication_sequences(P.pubname))");
    +
    
    I find that the complexity might stem from checking different cases in
    one function,  but I don't have better ideas to improve the logic for
    now. I think we can at least describe what the caller can expect from
    specifying only_sequence to true.
    
    ---
    +    * apply workers initilization, and to handle origin creation dynamically
    
    s/initilization/initialization/
    
    Regards,
    
    --
    Masahiko Sawada
    Amazon Web Services: https://aws.amazon.com
    
    
    
    
  415. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-21T04:03:29Z

    On Mon, Oct 20, 2025 at 5:29 PM Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > > Here is the latest patch set which addressed Shveta[1], Amit[2], Chao[3][4],
    > > Dilip[5], Sawada-San's[6] comments.
    >
    > I found the patch could not pass the sanity check, because 0001 missed a comma.
    > Also, there was a duplicated entry for `REFRESH SEQUENCES`.
    >
    > Attached set fixed the issue.
    >
    
    Thanks for the patch. I tried to compile the doc of patch001 alone. It
    did not go through, errors:
    
    postgres.sgml:198: element xref: validity error : IDREF attribute
    linkend references an unknown ID "sequence-definition-mismatches"
    postgres.sgml:234: element xref: validity error : IDREF attribute
    linkend references an unknown ID "sequence-definition-mismatches"
    postgres.sgml:239: element xref: validity error : IDREF attribute
    linkend references an unknown ID "sequences-out-of-sync"
    
    thanks
    Shveta
    
    
    
    
  416. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-21T06:56:12Z

    On Mon, Oct 20, 2025 at 5:29 PM Hayato Kuroda (Fujitsu)
    <kuroda.hayato@fujitsu.com> wrote:
    >
    > > Here is the latest patch set which addressed Shveta[1], Amit[2], Chao[3][4],
    > > Dilip[5], Sawada-San's[6] comments.
    >
    > I found the patch could not pass the sanity check, because 0001 missed a comma.
    > Also, there was a duplicated entry for `REFRESH SEQUENCES`.
    >
    > Attached set fixed the issue.
    >
    
    Some minor comments on 0001:
    
    >
    +
    +# This tests that sequences are synced correctly to the subscriber
    >
    
    Is this comment okay for 0001? How about: This tests that sequences
    are registered to be synced to the subscriber?
    
    +# Avoid checkpoint during the test, otherwise, extra values will be fetched for
    +# the sequences which will cause the test to fail randomly.
    +$node_publisher->init(allows_streaming => 'logical');
    +$node_publisher->append_conf('postgresql.conf', 'checkpoint_timeout = 1h');
    
    Do we need to set this additional GUC for 0001? I understand it could
    be required for 0002 though.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  417. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-21T09:37:13Z

    Few trivial comments on 001:
    
    patch001:
    
    1)
    FetchRelationStates
      /* Fetch tables and sequences that are in non-ready state. */
    - rstates = GetSubscriptionRelations(MySubscription->oid, true);
    + rstates = GetSubscriptionRelations(MySubscription->oid, true, false,
    +    true);
    
    We are passing get_Sequenecs as false, we should update comment to get
    rid of 'sequences;
    
    2)
    + /*
    + * XXX The walsender currently does not transmit the relkind of the remote
    + * relation when replicating changes. Since we support replicating only
    + * table changes at present, we default to initializing relkind as
    + * RELKIND_RELATION.
    + */
    + entry->remoterel.relkind = remoterel->relkind
    + ? remoterel->relkind : RELKIND_RELATION;
    
    Shall we also mention that currently this is used or needed only for
    CheckSubscriptionRelkind().
    
    ~~
    
    Few on 002:
    
    3)
    sequencesync.c:
    
    + * Executing the following command resets all sequences in the subscription to
    + * state DATASYNC, triggering re-synchronization:
    + * ALTER SUBSCRIPTION ... REFRESH SEQUENCES
    
    + * Sequence state transitions follow this pattern:
    + *   INIT / DATASYNC → READY
    
    These comments need correction. We no longer use DATASYNC state for seq.
    
    4)
    + * To avoid creating too many transactions, up to MAX_SEQUENCES_SYNC_PER_BATCH
    + * (100) sequences are synchronized per transaction. The locks on the sequence
    
    We can avoid writing 100 here. Mention of macro is enough.
    
    5)
    I had some 250 sequences; dropped one on pub, and ran 'refresh
    sequences' on sub, noticed few issues:
    
    a) Seqsync worker logged below but actually did not remove it. It
    seems it is some pending log from previous implementation:
    
    LOG:  sequences not found on publisher removed from resynchronization:
    ("public.myseq250")
    
    b) It kept on restarting the seq sync worker very fast. It should have
    waited for wal_retrieve_retry_interval (which is 5s in my env) to
    attempt restarting, isn't it? Logs:
    ----
    14:27:53.492 IST [72327] LOG:  logical replication sequence
    synchronization worker for subscription "sub1" has started
    14:27:53.499 IST [72327] LOG:  logical replication sequence
    synchronization for subscription "sub1" - total unsynchronized: 1
    14:27:53.500 IST [72327] LOG:  logical replication sequence
    synchronization for subscription "sub1" - batch #1 = 1 attempted, 0
    succeeded, 0 skipped, 0 mismatched, 0 insufficient permission, 1
    missing from publisher
    14:27:53.500 IST [72327] LOG:  sequences not found on publisher
    removed from resynchronization: ("public.myseq250")
    14:27:53.500 IST [72327] LOG:  logical replication sequence
    synchronization worker for subscription "sub1" has finished
    14:27:53.503 IST [72329] LOG:  logical replication sequence
    synchronization worker for subscription "sub1" has started
    14:27:53.508 IST [72329] LOG:  logical replication sequence
    synchronization for subscription "sub1" - total unsynchronized: 1
    ----
    
    c) Should this case give a suggestion/HINT in log to run 'REFERSH PUB'
    to correct sequence mapping.
    
    thanks
    Shveta
    
    
    
    
  418. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-21T14:41:35Z

    On Tue, 21 Oct 2025 at 03:49, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > On Mon, Oct 20, 2025 at 4:59 AM Hayato Kuroda (Fujitsu)
    > <kuroda.hayato@fujitsu.com> wrote:
    > >
    > > > Here is the latest patch set which addressed Shveta[1], Amit[2], Chao[3][4],
    > > > Dilip[5], Sawada-San's[6] comments.
    > >
    > > I found the patch could not pass the sanity check, because 0001 missed a comma.
    > > Also, there was a duplicated entry for `REFRESH SEQUENCES`.
    > >
    > > Attached set fixed the issue.
    > >
    >
    > Thank you for updating the patch! I have a few comments on the 0001 patch:
    >
    > -       appendStringInfo(&cmd, "SELECT DISTINCT n.nspname, c.relname,
    > gpt.attrs\n"
    > -                        "       FROM pg_class c\n"
    > +       appendStringInfo(&cmd, "SELECT DISTINCT n.nspname, c.relname,
    > gpt.attrs");
    > +
    > +       if (support_relkind_seq)
    > +           appendStringInfo(&cmd, ", c.relkind\n");
    > +
    > +       appendStringInfo(&cmd, "   FROM pg_class c\n"
    >                          "         JOIN pg_namespace n ON n.oid =
    > c.relnamespace\n"
    >                          "         JOIN ( SELECT
    > (pg_get_publication_tables(VARIADIC array_agg(pubname::text))).*\n"
    >                          "                FROM pg_publication\n"
    >                          "                WHERE pubname IN ( %s )) AS gpt\n"
    >                          "             ON gpt.relid = c.oid\n",
    >                          pub_names->data);
    >
    > I think we don't necessarily need to avoid getting relkind for servers
    > older than 19. IIUC the reason why we had to have check_columnlist was
    > that the attnames column was introduced to pg_publication_tables
    > catalog. But I think this patch is not the case since we get relkind
    > from pg_class. That is, I think we can get 4 columns from server >=16.
    
    Modified
    
    > ---
    >  /*
    > - * Check and log a warning if the publisher has subscribed to the same table,
    > - * its partition ancestors (if it's a partition), or its partition children (if
    > - * it's a partitioned table), from some other publishers. This check is
    > - * required in the following scenarios:
    > + * Check and log a warning if the publisher has subscribed to the same relation
    > + * (table or sequence), its partition ancestors (if it's a partition), or its
    > + * partition children (if it's a partitioned table), from some other
    > publishers.
    > + * This check is required in the following scenarios:
    >   *
    >   * 1) For CREATE SUBSCRIPTION and ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    >   *    statements with "copy_data = true" and "origin = none":
    >   *    - Warn the user that data with an origin might have been copied.
    > - *    - This check is skipped for tables already added, as incremental sync via
    > - *      WAL allows origin tracking. The list of such tables is in
    > - *      subrel_local_oids.
    > + *    - This check is skipped for tables and sequences already added, as
    > + *      incremental sync via WAL allows origin tracking. The list of
    > such tables
    > + *      is in subrel_local_oids.
    >   *
    >   * 2) For CREATE SUBSCRIPTION and ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    >   *    statements with "retain_dead_tuples = true" and "origin = any", and for
    > @@ -2338,13 +2440,19 @@ AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
    >   *    - Warn the user that only conflict detection info for local changes on
    >   *      the publisher is retained. Data from other origins may lack sufficient
    >   *      details for reliable conflict detection.
    > + *    - This check targets for tables only.
    >   *    - See comments atop worker.c for more details.
    > + *
    > + * 3) For ALTER SUBSCRIPTION ... REFRESH SEQUENCE statements with "origin =
    > + *    none":
    > + *    - Warn the user that sequence data from another origin might have been
    > + *      copied.
    >   */
    >
    > While this function is well documented, I find it's quite complex, and
    > this patch adds to that complexity. The function has 9 arguments,
    > making it difficult to understand which combinations of arguments
    > enable which checks. For example, the function header comment doesn't
    > explain when to use the only_sequences parameter. At first, I thought
    > only_sequences should be set to true when checking if the publisher
    > has subscribed to sequences from other publishers, but looking at the
    > code, I discovered it doesn't check sequences when check_rdt is true:
    >
    > +   if (walrcv_server_version(wrconn) < 190000 || check_rdt)
    > +       appendStringInfo(&cmd, query,
    > +                        "(SELECT relid, TRUE as istable FROM
    > pg_get_publication_tables(P.pubname))");
    > +   else if (only_sequences)
    > +       appendStringInfo(&cmd, query,
    > +                        "(SELECT relid, FALSE as istable FROM
    > pg_get_publication_sequences(P.pubname))");
    > +   else
    > +       appendStringInfo(&cmd, query,
    > +                        "(SELECT relid, TRUE as istable FROM
    > pg_get_publication_tables(P.pubname) UNION ALL"
    > +                        " SELECT relid, FALSE as istable FROM
    > pg_get_publication_sequences(P.pubname))");
    > +
    >
    > I find that the complexity might stem from checking different cases in
    > one function,  but I don't have better ideas to improve the logic for
    > now. I think we can at least describe what the caller can expect from
    > specifying only_sequence to true.
    
    Split this function into check_publications_origin_sequences and
    check_publications_origin_tables to reduce the complexity. After this
    change we log two warnings if both tables and sequences are subscriber
    to the same tables and sequences like:
    WARNING:  subscription "sub1" requested copy_data with origin = NONE
    but might copy data that had a different origin
    DETAIL:  The subscription subscribes to a publication ("pub1") that
    contains tables that are written to by other subscriptions.
    HINT:  Verify that initial data copied from the publisher tables did
    not come from other origins.
    WARNING:  subscription "sub1" requested copy_data with origin = NONE
    but might copy data that had a different origin
    DETAIL:  The subscription subscribes to a publication ("pub1") that
    contains sequences that are written to by other subscriptions.
    HINT:  Verify that initial data copied from the publisher sequences
    did not come from other origins.
    
    I felt it is ok, just highlighting here as this behavior will be seen
    in the new version. Here it will clearly mention that first message is
    from tables and second one is from sequences.
    
    > ---
    > +    * apply workers initilization, and to handle origin creation dynamically
    >
    > s/initilization/initialization/
    
    Modified
    
    Also Amit's comments from [1], Shveta's comments from [2] have been
    handled and Shveta's first patch comments from [3] has been handled.
    
    The attached patch has the changes for the same.
    
    [1] - https://www.postgresql.org/message-id/CAA4eK1Kobtqw3gf7RupcV%3DMYS53iHjgshVHQFTfL-n83XxucPg%40mail.gmail.com
    [2] - https://www.postgresql.org/message-id/CAJpy0uCvHmDdp7W1kDvVEwFT2%2BV9gnj5boE5%2BmtUqVknE9-bvQ%40mail.gmail.com
    [3] - https://www.postgresql.org/message-id/CAJpy0uDxms8ynrHWXHGFuxDLA7QzDLLASqpqdWnD%3DLa8UJPt7Q%40mail.gmail.com
    
    Regards,
    Vignesh
    
  419. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-22T02:21:50Z

    Hi Vignesh, Here are a few small review comments just for the docs
    part of patch 0001:
    
    ======
    Commit message
    
    1.
    In addition to the new command, the following subscription commands have
    been enhanced to automatically refresh sequence mappings:
    
    ~
    
    Is "mappings" the right word?
    
    ======
    doc/src/sgml/ref/alter_subscription.sgml
    
    2.
              <para>
    -          When false, the command will not try to refresh table information.
    -          <literal>REFRESH PUBLICATION</literal> should then be
    executed separately.
    -          The default is <literal>true</literal>.
    +          When false, the command will not try to refresh table and sequence
    +          information. <literal>REFRESH PUBLICATION</literal> should then be
    +          executed separately. The default is <literal>true</literal>.
              </para>
    
    I thought false should use markup: <literal>false</literal>  (just
    like true does)
    
    ~~~
    
    3.
    +         <para>
    +          Previously subscribed sequences are not re-synchronized. To do that,
    +          see <link linkend="sql-altersubscription-params-refresh-sequences">
    +          <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>.
    +         </para>
    
    /To do that, see/To do that, use/
    
    ~~~
    
    4.
    +     <para>
    +      Re-synchronize sequence data with the publisher. Unlike
    +      <link linkend="sql-altersubscription-params-refresh-publication">
    +      <literal>ALTER SUBSCRIPTION ... REFRESH
    PUBLICATION</literal></link> which
    +      only synchronizes newly added sequences, <literal>REFRESH
    SEQUENCES</literal>
    +      will re-synchronize the sequence data for all subscribed sequences. It
    +      does not add or remove the missing publication sequences from the
    +      subscription.
    +     </para>
    
    4a.
    IMO the ALTER SUBSCRIPTION command should have <command> markup
    instead of <literal>
    
    ~
    
    4b.
    I wondered if that part "...for all subscribed sequences" should say
    "...for all currently subscribed sequences", just for more clarity.
    
    ~
    
    4c.
    I do not think you need to say "the missing" here; IMO, that just
    leads to more questions -- missing from where? How do you remove
    something that is missing? etc. The suggestion below removes the
    ambiguity.
    
    SUGGESTION:
    It does not add or remove sequences from the subscription to match the
    publication.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  420. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-22T05:05:49Z

    On Tue, Oct 21, 2025 at 8:11 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 21 Oct 2025 at 03:49, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    >
    > > ---
    > >  /*
    > > - * Check and log a warning if the publisher has subscribed to the same table,
    > > - * its partition ancestors (if it's a partition), or its partition children (if
    > > - * it's a partitioned table), from some other publishers. This check is
    > > - * required in the following scenarios:
    > > + * Check and log a warning if the publisher has subscribed to the same relation
    > > + * (table or sequence), its partition ancestors (if it's a partition), or its
    > > + * partition children (if it's a partitioned table), from some other
    > > publishers.
    > > + * This check is required in the following scenarios:
    > >   *
    > >   * 1) For CREATE SUBSCRIPTION and ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > >   *    statements with "copy_data = true" and "origin = none":
    > >   *    - Warn the user that data with an origin might have been copied.
    > > - *    - This check is skipped for tables already added, as incremental sync via
    > > - *      WAL allows origin tracking. The list of such tables is in
    > > - *      subrel_local_oids.
    > > + *    - This check is skipped for tables and sequences already added, as
    > > + *      incremental sync via WAL allows origin tracking. The list of
    > > such tables
    > > + *      is in subrel_local_oids.
    > >   *
    > >   * 2) For CREATE SUBSCRIPTION and ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > >   *    statements with "retain_dead_tuples = true" and "origin = any", and for
    > > @@ -2338,13 +2440,19 @@ AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
    > >   *    - Warn the user that only conflict detection info for local changes on
    > >   *      the publisher is retained. Data from other origins may lack sufficient
    > >   *      details for reliable conflict detection.
    > > + *    - This check targets for tables only.
    > >   *    - See comments atop worker.c for more details.
    > > + *
    > > + * 3) For ALTER SUBSCRIPTION ... REFRESH SEQUENCE statements with "origin =
    > > + *    none":
    > > + *    - Warn the user that sequence data from another origin might have been
    > > + *      copied.
    > >   */
    > >
    > > While this function is well documented, I find it's quite complex, and
    > > this patch adds to that complexity. The function has 9 arguments,
    > > making it difficult to understand which combinations of arguments
    > > enable which checks. For example, the function header comment doesn't
    > > explain when to use the only_sequences parameter. At first, I thought
    > > only_sequences should be set to true when checking if the publisher
    > > has subscribed to sequences from other publishers, but looking at the
    > > code, I discovered it doesn't check sequences when check_rdt is true:
    > >
    > > +   if (walrcv_server_version(wrconn) < 190000 || check_rdt)
    > > +       appendStringInfo(&cmd, query,
    > > +                        "(SELECT relid, TRUE as istable FROM
    > > pg_get_publication_tables(P.pubname))");
    > > +   else if (only_sequences)
    > > +       appendStringInfo(&cmd, query,
    > > +                        "(SELECT relid, FALSE as istable FROM
    > > pg_get_publication_sequences(P.pubname))");
    > > +   else
    > > +       appendStringInfo(&cmd, query,
    > > +                        "(SELECT relid, TRUE as istable FROM
    > > pg_get_publication_tables(P.pubname) UNION ALL"
    > > +                        " SELECT relid, FALSE as istable FROM
    > > pg_get_publication_sequences(P.pubname))");
    > > +
    > >
    > > I find that the complexity might stem from checking different cases in
    > > one function,  but I don't have better ideas to improve the logic for
    > > now. I think we can at least describe what the caller can expect from
    > > specifying only_sequence to true.
    >
    > Split this function into check_publications_origin_sequences and
    > check_publications_origin_tables to reduce the complexity. After this
    > change we log two warnings if both tables and sequences are subscriber
    > to the same tables and sequences like:
    >
    
    I think the case where both WARNINGs will be displayed is rare so it
    should be okay as it simplifies the code quite a bit. Another thing is
    we need to query twice but as this happens during DDL and only for
    very specific cases that should also be okay. We can anyway merge
    these later if we see any problem with it but for now it would be
    better to prefer code simplicity.
    
    When check_publications_origin_sequences() is called from Alter
    Subscription ... Refresh Publication ... or Create Subscription ...
    code path then shouldn't we check copy_data as well along with origin
    as none? Because, if copy_data is false, we should have added a
    sequence in the READY state, so we don't need to fetch its values.
    
    I have added a few comments in this new function and made a number of
    other cosmetic improvements in the attached.
    
    -- 
    With Regards,
    Amit Kapila.
    
  421. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-22T05:23:03Z

    Hi Vignesh,
    
    Here are a few review comments for patch 0001:
    
    ======
    src/backend/catalog/pg_subscription.c
    
    GetSubscriptionRelations:
    
    1.
     List *
    -GetSubscriptionRelations(Oid subid, bool not_ready)
    +GetSubscriptionRelations(Oid subid, bool otherwise return all the
    relations of the subscription, bool get_sequences,
    + bool not_ready)
    
    Now the function parameter means the (unchanged) function comment is
    not correct anymore.
    
    e.g. It still says "otherwise return all the relations of the
    subscription", but that does not account for the parameters indicating
    if you only want tables, or only want sequences.
    
    ======
    src/backend/commands/subscriptioncmds.c
    
    2.
    +typedef struct PublicationRelKind
    +{
    + RangeVar   *rv;
    + char relkind;
    +} PublicationRelKind;
    +
    
    Is this deserving of a comment to saying what it is for?
    
    ~~~
    
    CreateSubscription:
    
    3.
    + *
    + * Similar to origins, it is not clear whether preventing the slot
    + * creation for empty and sequence-only subscriptions is worth
    + * additional complexity.
      */
    
    I think this "Similar to..." comment needs "XXX", same as the earlier
    comment it is referring to.
    
    ~~~
    
    AlterSubscription_refresh:
    
    4.
    + * Build qsorted array of local relation oids for faster lookup. This
    + * can potentially contain all relation in the database so speed of
    + * lookup is important.
    + *
    
    /all relation/all relations/
    
    ~~~
    
    5.
    - qsort(subrel_local_oids, subrel_count,
    + qsort(subrel_local_oids, tbl_count,
        sizeof(Oid), oid_cmp);
    
    - check_publications_origin(wrconn, sub->publications, copy_data,
    -   sub->retaindeadtuples, sub->origin,
    -   subrel_local_oids, subrel_count, sub->name);
    + check_publications_origin_tables(wrconn, sub->publications, copy_data,
    + sub->retaindeadtuples, sub->origin,
    + subrel_local_oids, tbl_count,
    + sub->name);
    
    - /*
    - * Rels that we want to remove from subscription and drop any slots
    - * and origins corresponding to them.
    - */
    - sub_remove_rels = palloc(subrel_count * sizeof(SubRemoveRels));
    + qsort(subseq_local_oids, seq_count, sizeof(Oid), oid_cmp);
    + check_publications_origin_sequences(wrconn, sub->publications,
    + sub->origin, subseq_local_oids,
    + seq_count, sub->name);
    
    The first qsort wrapping and the blank line spacing are a bit inconsistent here.
    
    ~~~
    
    6.
    +static void
    +check_publications_origin_sequences(WalReceiverConn *wrconn, List
    *publications,
    + char *origin, Oid *subrel_local_oids,
    + int subrel_count, char *subname)
    
    Deserving of a function comment?
    
    ~
    
    7.
    + for (i = 0; i < subrel_count; i++)
    + {
    
    Declare 'i' as a for-loop variable.
    
    ~
    
    8.
    + if (res->status != WALRCV_OK_TUPLES)
    + ereport(ERROR,
    + (errcode(ERRCODE_CONNECTION_FAILURE),
    + errmsg("could not receive list of replicated relations from the
    publisher: %s",
    + res->err)));
    +
    + /* Process relations. */
    + slot = MakeSingleTupleTableSlot(res->tupledesc, &TTSOpsMinimalTuple);
    + while (tuplestore_gettupleslot(res->tuplestore, true, false, slot))
    
    Since this function is just for sequences, should it say "replicated
    sequences" instead of "relations" here?
    
    Similarly, should the "Process relations" maybe say "Process sequence
    relations" or "Process sequences"?
    
    ~~~
    
    fetch_table_list:
    
    9.
    + appendStringInfo(&cmd,
    + "UNION ALL\n"
    + "  SELECT DISTINCT s.schemaname, s.sequencename, NULL::int2vector AS
    attrs, " CppAsString2(RELKIND_SEQUENCE) "::\"char\" AS relkind\n"
    + "  FROM pg_catalog.pg_publication_sequences s\n"
    + "  WHERE s.pubname IN (%s)",
    + pub_names->data);
    
    Missing a final \n?
    
    ======
    src/backend/replication/logical/syncutils.c
    
    10.
    bool
    FetchRelationStates(bool *started_tx)
    
    IIUC, you are using the terminology "relations" to apply to both
    tables or sequences; OTOH ", tables" is just tables. It seems this
    function is table-specific. Should it have a name change like
    FetchTableStates?
    
    ======
    src/test/subscription/t/036_sequences.pl
    
    11.
    There are no test cases checking that ALTER commands will correctly
    add/remove sequences in the pg_subscription_rel?
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  422. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-22T05:31:40Z

    On Wed, Oct 22, 2025 at 10:36 AM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    >
    > I think the case where both WARNINGs will be displayed is rare so it
    > should be okay as it simplifies the code quite a bit. Another thing is
    > we need to query twice but as this happens during DDL and only for
    > very specific cases that should also be okay. We can anyway merge
    > these later if we see any problem with it but for now it would be
    > better to prefer code simplicity.
    >
    
    +1
    
    Few trivial comments on 001:
    
    1)
    In fetch_relation_list(), I feel support_relkind is misleading as now
    we are unconditionally supporting fetching relkind once the version >=
    16. We can make the function work without having this variable.
    
    2)
    + * Build qsorted array of local relation oids for faster lookup. This
    + * can potentially contain all relation in the database so speed of
    + * lookup is important.
    
    Since we are building multiple arrays now, we can change comment to:
    Build qsorted arrays of local table oids and sequence oids for faster
    lookup. This can potentially contain all tables and sequences in the
    database so speed of lookup is important.
    
    thanks
    Shveta
    
    
    
    
  423. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-22T05:37:10Z

    On Wed, Oct 22, 2025 at 10:53 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Here are a few review comments for patch 0001:
    >
    > ======
    > src/backend/catalog/pg_subscription.c
    >
    > GetSubscriptionRelations:
    >
    > 1.
    >  List *
    > -GetSubscriptionRelations(Oid subid, bool not_ready)
    > +GetSubscriptionRelations(Oid subid, bool otherwise return all the
    > relations of the subscription, bool get_sequences,
    > + bool not_ready)
    >
    > Now the function parameter means the (unchanged) function comment is
    > not correct anymore.
    >
    > e.g. It still says "otherwise return all the relations of the
    > subscription", but that does not account for the parameters indicating
    > if you only want tables, or only want sequences.
    >
    
    I think the code for those parameters is quite clear. The previous
    version had few comments but I found those unnecessary.
    
    > src/backend/replication/logical/syncutils.c
    >
    > 10.
    > bool
    > FetchRelationStates(bool *started_tx)
    >
    > IIUC, you are using the terminology "relations" to apply to both
    > tables or sequences; OTOH ", tables" is just tables. It seems this
    > function is table-specific. Should it have a name change like
    > FetchTableStates?
    >
    
    The patch 0002 has some changes related to sequences in this function.
    So, I think the current naming is okay.
    
    > ======
    > src/test/subscription/t/036_sequences.pl
    >
    > 11.
    > There are no test cases checking that ALTER commands will correctly
    > add/remove sequences in the pg_subscription_rel?
    >
    
    The patch 0002 has tests related to ALTER commands. I don't think 0001
    needs tests for all kinds of statements as both will be committed a
    few days apart.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  424. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-22T05:40:52Z

    On Wed, Oct 22, 2025 at 7:52 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh, Here are a few small review comments just for the docs
    > part of patch 0001:
    >
    > ======
    > Commit message
    >
    > 1.
    > In addition to the new command, the following subscription commands have
    > been enhanced to automatically refresh sequence mappings:
    >
    > ~
    >
    > Is "mappings" the right word?
    >
    
    I think so because pg_subscription_rel has mappings of relations in
    publisher and subscriber.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  425. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-23T06:15:17Z

    On Wed, 22 Oct 2025 at 10:36, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Tue, Oct 21, 2025 at 8:11 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Tue, 21 Oct 2025 at 03:49, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
    > >
    > > > ---
    > > >  /*
    > > > - * Check and log a warning if the publisher has subscribed to the same table,
    > > > - * its partition ancestors (if it's a partition), or its partition children (if
    > > > - * it's a partitioned table), from some other publishers. This check is
    > > > - * required in the following scenarios:
    > > > + * Check and log a warning if the publisher has subscribed to the same relation
    > > > + * (table or sequence), its partition ancestors (if it's a partition), or its
    > > > + * partition children (if it's a partitioned table), from some other
    > > > publishers.
    > > > + * This check is required in the following scenarios:
    > > >   *
    > > >   * 1) For CREATE SUBSCRIPTION and ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > > >   *    statements with "copy_data = true" and "origin = none":
    > > >   *    - Warn the user that data with an origin might have been copied.
    > > > - *    - This check is skipped for tables already added, as incremental sync via
    > > > - *      WAL allows origin tracking. The list of such tables is in
    > > > - *      subrel_local_oids.
    > > > + *    - This check is skipped for tables and sequences already added, as
    > > > + *      incremental sync via WAL allows origin tracking. The list of
    > > > such tables
    > > > + *      is in subrel_local_oids.
    > > >   *
    > > >   * 2) For CREATE SUBSCRIPTION and ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > > >   *    statements with "retain_dead_tuples = true" and "origin = any", and for
    > > > @@ -2338,13 +2440,19 @@ AlterSubscriptionOwner_oid(Oid subid, Oid newOwnerId)
    > > >   *    - Warn the user that only conflict detection info for local changes on
    > > >   *      the publisher is retained. Data from other origins may lack sufficient
    > > >   *      details for reliable conflict detection.
    > > > + *    - This check targets for tables only.
    > > >   *    - See comments atop worker.c for more details.
    > > > + *
    > > > + * 3) For ALTER SUBSCRIPTION ... REFRESH SEQUENCE statements with "origin =
    > > > + *    none":
    > > > + *    - Warn the user that sequence data from another origin might have been
    > > > + *      copied.
    > > >   */
    > > >
    > > > While this function is well documented, I find it's quite complex, and
    > > > this patch adds to that complexity. The function has 9 arguments,
    > > > making it difficult to understand which combinations of arguments
    > > > enable which checks. For example, the function header comment doesn't
    > > > explain when to use the only_sequences parameter. At first, I thought
    > > > only_sequences should be set to true when checking if the publisher
    > > > has subscribed to sequences from other publishers, but looking at the
    > > > code, I discovered it doesn't check sequences when check_rdt is true:
    > > >
    > > > +   if (walrcv_server_version(wrconn) < 190000 || check_rdt)
    > > > +       appendStringInfo(&cmd, query,
    > > > +                        "(SELECT relid, TRUE as istable FROM
    > > > pg_get_publication_tables(P.pubname))");
    > > > +   else if (only_sequences)
    > > > +       appendStringInfo(&cmd, query,
    > > > +                        "(SELECT relid, FALSE as istable FROM
    > > > pg_get_publication_sequences(P.pubname))");
    > > > +   else
    > > > +       appendStringInfo(&cmd, query,
    > > > +                        "(SELECT relid, TRUE as istable FROM
    > > > pg_get_publication_tables(P.pubname) UNION ALL"
    > > > +                        " SELECT relid, FALSE as istable FROM
    > > > pg_get_publication_sequences(P.pubname))");
    > > > +
    > > >
    > > > I find that the complexity might stem from checking different cases in
    > > > one function,  but I don't have better ideas to improve the logic for
    > > > now. I think we can at least describe what the caller can expect from
    > > > specifying only_sequence to true.
    > >
    > > Split this function into check_publications_origin_sequences and
    > > check_publications_origin_tables to reduce the complexity. After this
    > > change we log two warnings if both tables and sequences are subscriber
    > > to the same tables and sequences like:
    > >
    >
    > I think the case where both WARNINGs will be displayed is rare so it
    > should be okay as it simplifies the code quite a bit. Another thing is
    > we need to query twice but as this happens during DDL and only for
    > very specific cases that should also be okay. We can anyway merge
    > these later if we see any problem with it but for now it would be
    > better to prefer code simplicity.
    
    I agree.
    
    > When check_publications_origin_sequences() is called from Alter
    > Subscription ... Refresh Publication ... or Create Subscription ...
    > code path then shouldn't we check copy_data as well along with origin
    > as none? Because, if copy_data is false, we should have added a
    > sequence in the READY state, so we don't need to fetch its values.
    
    Fixed this.
    
    > I have added a few comments in this new function and made a number of
    > other cosmetic improvements in the attached.
    
    Thanks for the changes, I merged it.
    
    The attached patch has the changes for the same.
    I have also addressed the other comments: a) Shveta's comments at [1]
    b) Peter's comments at [2] & [3] c) Shveta's 2nd patch comments at [4]
    and d) Chao's comment#12 from [5] which was pending.
    
    [1] - https://www.postgresql.org/message-id/CAJpy0uDesLXjpDiDs6fA8HMr419D2YrXb7tA10e9Bp%2BuCypZ_Q%40mail.gmail.com
    [2] - https://www.postgresql.org/message-id/CAHut%2BPtp%2BFMHgS-kaKZwWEoNeyomecUDGECvoCpfx4_eCUDyUA%40mail.gmail.com
    [3] - https://www.postgresql.org/message-id/CAHut%2BPvx945dJGhMtf2Rv5p8Xn4xQke65MfO-UwK3cRPnsXFRQ%40mail.gmail.com
    [4] - https://www.postgresql.org/message-id/CAJpy0uDxms8ynrHWXHGFuxDLA7QzDLLASqpqdWnD%3DLa8UJPt7Q%40mail.gmail.com
    [5] - https://www.postgresql.org/message-id/598FC353-8E9A-4857-A125-740BE24DCBEB%40gmail.com
    
    
    Regards,
    Vignesh
    
  426. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-23T11:17:24Z

    On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > The attached patch has the changes for the same.
    >
    
    I have pushed 0001 and the following are comments on 0002.
    
    1.
    @@ -1414,6 +1414,7 @@ CREATE VIEW pg_stat_subscription_stats AS
             ss.subid,
             s.subname,
             ss.apply_error_count,
    +        ss.sequence_sync_error_count,
             ss.sync_error_count,
    
    The new parameter name is noticeably longer than other columns. Can we
    name it as ss.seq_sync_error_count. We may also want to reconsider
    changing existing column sync_error_count to tbl_sync_error_count. Can
    we extract this in a separate stats patch?
    
    2.
     Datum
     pg_get_sequence_data(PG_FUNCTION_ARGS)
    @@ -1843,6 +1843,13 @@ pg_get_sequence_data(PG_FUNCTION_ARGS)
    
      values[0] = Int64GetDatum(seq->last_value);
      values[1] = BoolGetDatum(seq->is_called);
    +
    + /*
    + * The page LSN will be used in logical replication of sequences to
    + * record the LSN of the sequence page in the pg_subscription_rel
    + * system catalog.  It reflects the LSN of the remote sequence at the
    + * time it was synchronized.
    + */
      values[2] = LSNGetDatum(PageGetLSN(page));
    
    This comment appears out of place. We should mention it somewhere in
    sequencesync worker and give reference of that place/function here.
    
    3.
    LogicalRepWorker *
    -logicalrep_worker_find(Oid subid, Oid relid, bool only_running)
    +logicalrep_worker_find(Oid subid, Oid relid, LogicalRepWorkerType wtype,
    +    bool only_running)
    …
    …
     void
    -logicalrep_worker_stop(Oid subid, Oid relid)
    +logicalrep_worker_stop(Oid subid, Oid relid, LogicalRepWorkerType wtype)
    
    Let's extract changes for these APIs and their callers in a separate
    patch that can be committed prior to the main patch.
    
    4.
    +void
    +logicalrep_reset_seqsync_start_time(void)
    +{
    + LogicalRepWorker *worker;
    +
    + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
    +
    + worker = logicalrep_worker_find(MyLogicalRepWorker->subid, InvalidOid,
    + WORKERTYPE_APPLY, true);
    
    Shouldn't WORKERTYPE_SEQUENCESYNC be used? If not, then better to add
    a comment on why a different type of worker is used for resetting the
    seqsync time.
    
    5.
    + * XXX: An alternative design was considered where the launcher process would
    …
    ...
    + * c) It utilizes the existing tablesync worker code to start the sequencesync
    + *    process, thus preventing code duplication in the launcher.
    + * d) It simplifies code maintenance by consolidating changes to a single
    + *    location rather than multiple components.
    + * e) The apply worker can access the sequences that need to be synchronized
    + *    from the pg_subscription_rel system catalog. Whereas the launcher process
    + *    operates without direct database access so would need a framework to
    + *    establish connections with the databases to retrieve the sequences for
    + *    synchronization.
    
    Only these three points are sufficient for not going with this
    alternative approach. The point (e) is most important and should be
    mentioned as the first point.
    
    6.
    + /* Get the local sequence object */
    + sequence_rel = try_table_open(seqinfo->localrelid, RowExclusiveLock);
    + tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    + if (!sequence_rel || !HeapTupleIsValid(tup))
    + {
    + (*skipped_count)++;
    + elog(LOG, "skip synchronization of sequence \"%s.%s\" because it has
    been dropped concurrently",
    + nspname, seqname);
    + return;
    
    We should close the relation when the tuple is not valid and can't proceed.
    
    7.
    + /* Skip if the entry is no longer valid */
    + if (!seqinfo->entry_valid)
    + {
    + ReleaseSysCache(tup);
    + table_close(sequence_rel, RowExclusiveLock);
    + (*skipped_count)++;
    + ereport(LOG, errmsg("skip synchronization of sequence \"%s.%s\"
    because it has been altered concurrently",
    + nspname, seqname));
    + return;
    
    Isn't it better to release cache and close relation just before
    return? Tomorrow, if we need to use something from tuple/relation, it
    would be easier.
    
    8.
    +LogicalRepSyncSequences(void)
    {
    ...
    + ScanKeyInit(&skey[1],
    + Anum_pg_subscription_rel_srsubstate,
    + BTEqualStrategyNumber, F_CHARNE,
    + CharGetDatum(SUBREL_STATE_READY));
    
    As we are using only two states (INIT and READY) for sequences, isn't
    it better to use INIT state here? That should avoid sync-in-progress
    tables.
    
    9. I find the copy_sequences->copy_sequence code can be rearranged to
    make it easy to follow. The point I don't like is that the boundary
    between two makes it hard to follow and requires so many parameters to
    be passed to copy_sequence. The one idea to improve is to move all
    failure checks out of copy_sequence either directly in the caller or
    as a separate function. All the values for each sequence can be
    fetched in the caller and copy_sequence can be used to SetSequence and
    UpdateSubscriptionRelState(). If you have any better ideas to
    rearrange this part of the patch then feel free to try those out and
    share the results.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  427. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-24T03:25:49Z

    On Thursday, October 23, 2025 2:15 PM vignesh C <vignesh21@gmail.com> wrote:
    > The attached patch has the changes for the same.
    > I have also addressed the other comments: a) Shveta's comments at [1]
    > b) Peter's comments at [2] & [3] c) Shveta's 2nd patch comments at [4] and d)
    > Chao's comment#12 from [5] which was pending.
    
    Thanks for updating the patch, I have a few comments for 0002.
    
    1.
    
    +		hash_seq_init(&hash_seq, sequences_to_copy);
    +		while ((seq_entry = hash_seq_search(&hash_seq)) != NULL)
    +		{
    +			pfree(seq_entry->seqname);
    +			pfree(seq_entry->nspname);
    +		}
    +	}
    +
    +	hash_destroy(sequences_to_copy);
    
    I personally feel these memory free calls are unnecessary since the sync worker
    will stop soon.
    
    
    2.
    -FinishSyncWorker(void)
    +FinishSyncWorker(LogicalRepWorkerType wtype)
    
    Can we directly access MyLogicalRepWorker->type instead of adding
    one func parameter ?
    
    
    3.
    
    						 "ORDER BY s.schname, s.seqname\n",
    
    Just to confirm, is this "ORDER BY" necessary for correctness ?
    
    
    4.
    
    		elog(LOG, "skip synchronization of sequence \"%s.%s\" because it has been dropped concurrently",
    			 nspname, seqname);
    
    Shall we use ereport here ?
    
    Best Regards,
    Hou zj
    
    
  428. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-24T06:13:17Z

    Please find a few comments for 002:
    
    1)
    sequencesync.c compiles without these inclusions:
    
    +#include "replication/logicallauncher.h"
    +#include "replication/worker_internal.h"
    +#include "utils/rls.h"
    
    2)
    SEQ_LOG_CNT_INVALID: it is not used anywhere.
    
    3)
    +## ALTER SUBSCRIPTION ... REFRESH SEQUENCES should cause sync of new sequences
    
    Comment seems incorrect, later one is correct:
    +# Check - newly published sequence is not synced
    
    4)
    +# ALTER SUBSCRIPTION ... REFRESH PUBLICATION should throw an error
    +# for sequence definition not matching between the publisher and the
    subscriber.
    
    Since we check for both non-matching and missing seq in the concerned
    test, we shall mention missing-seq in comment as well.
    
    5)
    For the race condition where the worker is going to access the seq
    locally and meanwhile it is altered; now the worker correctly reports
    this. But it reports this as a success scenario. And once the scenario
    is reported as 'seq-worker finished', we do not expect it to start
    running again without the user doing REFRESH. But in this case, it
    runs, see logs. Also it starts immediately for once due to the same
    reason that start_time is reset in the success scenario.
    -------
    17:35:05.618 IST [132551] LOG:  logical replication apply worker for
    subscription "sub1" has started
    17:35:05.637 IST [132553] LOG:  logical replication sequence
    synchronization worker for subscription "sub1" has started
    17:35:05.663 IST [132553] LOG:  logical replication sequence
    synchronization for subscription "sub1" - total unsynchronized: 1
    17:36:11.987 IST [132553] LOG:  skip synchronization of sequence
    "public.myseq249" because it has been altered concurrently
    17:36:19.614 IST [132553] LOG:  logical replication sequence
    synchronization for subscription "sub1" - batch #1 = 1 attempted, 0
    succeeded, 1 skipped, 0 mismatched, 0 insufficient permission, 0
    missing from publisher
    17:36:20.335 IST [132553] LOG:  logical replication sequence
    synchronization worker for subscription "sub1" has finished
    17:36:20.435 IST [132586] LOG:  logical replication sequence
    synchronization worker for subscription "sub1" has started
    17:36:20.545 IST [132586] LOG:  logical replication sequence
    synchronization for subscription "sub1" - total unsynchronized: 1
    -------
    
    The behaviour looks slightly odd. Is there anything we can do about
    this? Shall the skipped case be reported as ERROR due to the fact that
    we leave it in state 'i' in pg_subscription_rel?
    
    thanks
    Shveta
    
    
    
    
  429. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-24T15:22:04Z

    On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached patch has the changes for the same.
    > >
    >
    > I have pushed 0001 and the following are comments on 0002.
    >
    > 1.
    > @@ -1414,6 +1414,7 @@ CREATE VIEW pg_stat_subscription_stats AS
    >          ss.subid,
    >          s.subname,
    >          ss.apply_error_count,
    > +        ss.sequence_sync_error_count,
    >          ss.sync_error_count,
    >
    > The new parameter name is noticeably longer than other columns. Can we
    > name it as ss.seq_sync_error_count. We may also want to reconsider
    > changing existing column sync_error_count to tbl_sync_error_count. Can
    > we extract this in a separate stats patch?
    
    Modified and extracted a separate patch for tbl_sync_error_count
    
    > 2.
    >  Datum
    >  pg_get_sequence_data(PG_FUNCTION_ARGS)
    > @@ -1843,6 +1843,13 @@ pg_get_sequence_data(PG_FUNCTION_ARGS)
    >
    >   values[0] = Int64GetDatum(seq->last_value);
    >   values[1] = BoolGetDatum(seq->is_called);
    > +
    > + /*
    > + * The page LSN will be used in logical replication of sequences to
    > + * record the LSN of the sequence page in the pg_subscription_rel
    > + * system catalog.  It reflects the LSN of the remote sequence at the
    > + * time it was synchronized.
    > + */
    >   values[2] = LSNGetDatum(PageGetLSN(page));
    >
    > This comment appears out of place. We should mention it somewhere in
    > sequencesync worker and give reference of that place/function here.
    
    Moved this comment to the copy_sequence function just above
    UpdateSubscriptionRelState.
    
    > 3.
    > LogicalRepWorker *
    > -logicalrep_worker_find(Oid subid, Oid relid, bool only_running)
    > +logicalrep_worker_find(Oid subid, Oid relid, LogicalRepWorkerType wtype,
    > +    bool only_running)
    > …
    > …
    >  void
    > -logicalrep_worker_stop(Oid subid, Oid relid)
    > +logicalrep_worker_stop(Oid subid, Oid relid, LogicalRepWorkerType wtype)
    >
    > Let's extract changes for these APIs and their callers in a separate
    > patch that can be committed prior to the main patch.
    
    Prepared a separated patch
    
    > 4.
    > +void
    > +logicalrep_reset_seqsync_start_time(void)
    > +{
    > + LogicalRepWorker *worker;
    > +
    > + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
    > +
    > + worker = logicalrep_worker_find(MyLogicalRepWorker->subid, InvalidOid,
    > + WORKERTYPE_APPLY, true);
    >
    > Shouldn't WORKERTYPE_SEQUENCESYNC be used? If not, then better to add
    > a comment on why a different type of worker is used for resetting the
    > seqsync time.
    
    It should be apply worker here. We set the last_seqsync_start_time for
    the sequence worker in the apply worker instead of the sequence sync
    worker, as the sequence sync worker has finished and is about to exit.
    
    > 5.
    > + * XXX: An alternative design was considered where the launcher process would
    > …
    > ...
    > + * c) It utilizes the existing tablesync worker code to start the sequencesync
    > + *    process, thus preventing code duplication in the launcher.
    > + * d) It simplifies code maintenance by consolidating changes to a single
    > + *    location rather than multiple components.
    > + * e) The apply worker can access the sequences that need to be synchronized
    > + *    from the pg_subscription_rel system catalog. Whereas the launcher process
    > + *    operates without direct database access so would need a framework to
    > + *    establish connections with the databases to retrieve the sequences for
    > + *    synchronization.
    >
    > Only these three points are sufficient for not going with this
    > alternative approach. The point (e) is most important and should be
    > mentioned as the first point.
    
    Modified
    
    > 6.
    > + /* Get the local sequence object */
    > + sequence_rel = try_table_open(seqinfo->localrelid, RowExclusiveLock);
    > + tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    > + if (!sequence_rel || !HeapTupleIsValid(tup))
    > + {
    > + (*skipped_count)++;
    > + elog(LOG, "skip synchronization of sequence \"%s.%s\" because it has
    > been dropped concurrently",
    > + nspname, seqname);
    > + return;
    >
    > We should close the relation when the tuple is not valid and can't proceed.
    
    Modified slightly to check in validate_sequence and close the relation
    in copy_sequence.
    
    > 7.
    > + /* Skip if the entry is no longer valid */
    > + if (!seqinfo->entry_valid)
    > + {
    > + ReleaseSysCache(tup);
    > + table_close(sequence_rel, RowExclusiveLock);
    > + (*skipped_count)++;
    > + ereport(LOG, errmsg("skip synchronization of sequence \"%s.%s\"
    > because it has been altered concurrently",
    > + nspname, seqname));
    > + return;
    >
    > Isn't it better to release cache and close relation just before
    > return? Tomorrow, if we need to use something from tuple/relation, it
    > would be easier.
    
    Because of another comment, the code is re-structured now. As per
    current logic the tuple will be released in validate_sequence and the
    logging based on error is done at copy_sequence. For new code
    structure releasing tuple in validate_sequence is better
    
    > 8.
    > +LogicalRepSyncSequences(void)
    > {
    > ...
    > + ScanKeyInit(&skey[1],
    > + Anum_pg_subscription_rel_srsubstate,
    > + BTEqualStrategyNumber, F_CHARNE,
    > + CharGetDatum(SUBREL_STATE_READY));
    >
    > As we are using only two states (INIT and READY) for sequences, isn't
    > it better to use INIT state here? That should avoid sync-in-progress
    > tables.
    
    Modified
    
    > 9. I find the copy_sequences->copy_sequence code can be rearranged to
    > make it easy to follow. The point I don't like is that the boundary
    > between two makes it hard to follow and requires so many parameters to
    > be passed to copy_sequence. The one idea to improve is to move all
    > failure checks out of copy_sequence either directly in the caller or
    > as a separate function. All the values for each sequence can be
    > fetched in the caller and copy_sequence can be used to SetSequence and
    > UpdateSubscriptionRelState(). If you have any better ideas to
    > rearrange this part of the patch then feel free to try those out and
    > share the results.
    
    Modified
    
    The attached v20251024 version patch has the changes for the same.
    The comments from [1] have also been addressed in this version.
    
    [1] - https://www.postgresql.org/message-id/TY4PR01MB169078C625FB8980E6F42F4F994F1A%40TY4PR01MB16907.jpnprd01.prod.outlook.com
    
    Regards,
    Vignesh
    
  430. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-25T06:45:55Z

    On Fri, Oct 24, 2025 at 11:43 AM shveta malik <shveta.malik@gmail.com> wrote:
    >
    > 5)
    > For the race condition where the worker is going to access the seq
    > locally and meanwhile it is altered; now the worker correctly reports
    > this. But it reports this as a success scenario. And once the scenario
    > is reported as 'seq-worker finished', we do not expect it to start
    > running again without the user doing REFRESH. But in this case, it
    > runs, see logs. Also it starts immediately for once due to the same
    > reason that start_time is reset in the success scenario.
    > -------
    > 17:35:05.618 IST [132551] LOG:  logical replication apply worker for
    > subscription "sub1" has started
    > 17:35:05.637 IST [132553] LOG:  logical replication sequence
    > synchronization worker for subscription "sub1" has started
    > 17:35:05.663 IST [132553] LOG:  logical replication sequence
    > synchronization for subscription "sub1" - total unsynchronized: 1
    > 17:36:11.987 IST [132553] LOG:  skip synchronization of sequence
    > "public.myseq249" because it has been altered concurrently
    > 17:36:19.614 IST [132553] LOG:  logical replication sequence
    > synchronization for subscription "sub1" - batch #1 = 1 attempted, 0
    > succeeded, 1 skipped, 0 mismatched, 0 insufficient permission, 0
    > missing from publisher
    > 17:36:20.335 IST [132553] LOG:  logical replication sequence
    > synchronization worker for subscription "sub1" has finished
    > 17:36:20.435 IST [132586] LOG:  logical replication sequence
    > synchronization worker for subscription "sub1" has started
    > 17:36:20.545 IST [132586] LOG:  logical replication sequence
    > synchronization for subscription "sub1" - total unsynchronized: 1
    > -------
    >
    > The behaviour looks slightly odd. Is there anything we can do about
    > this? Shall the skipped case be reported as ERROR due to the fact that
    > we leave it in state 'i' in pg_subscription_rel?
    >
    
    The downside of reporting an ERROR as soon as we can't sync values for
    one of the sequences is that the other sequences which could be synced
    won't get synced. The other possibility is that we skip processing
    such a sequence while copying sequences but at the end if there is any
    pending sequence which is not synced, we raise an ERROR. If we do that
    then we may need to give some generic ERROR because there could be
    multiple such sequences. The other possibility is that we can give a
    LOG message like "logical replication sequence sync worker for
    subscription \"%s\" will restart because ..." and then do proc_exit(1)
    without resetting restart_time. Will that help to address your
    concern?
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  431. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-25T06:56:55Z

    On Fri, Oct 24, 2025 at 8:52 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > The attached patch has the changes for the same.
    > > >
    > >
    > > I have pushed 0001 and the following are comments on 0002.
    > >
    > > 1.
    > > @@ -1414,6 +1414,7 @@ CREATE VIEW pg_stat_subscription_stats AS
    > >          ss.subid,
    > >          s.subname,
    > >          ss.apply_error_count,
    > > +        ss.sequence_sync_error_count,
    > >          ss.sync_error_count,
    > >
    > > The new parameter name is noticeably longer than other columns. Can we
    > > name it as ss.seq_sync_error_count. We may also want to reconsider
    > > changing existing column sync_error_count to tbl_sync_error_count. Can
    > > we extract this in a separate stats patch?
    >
    > Modified and extracted a separate patch for tbl_sync_error_count
    >
    
    Hmm, I didn't want to make the stats related changes before the main
    patch. I suggested to extract seq_sync_error_count from the main patch
    and keep it after the main patch. Along with the seq_sync_error_count
    stats, we can discuss whether to change existing parameter to
    tbl_sync_error_count.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  432. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-27T02:53:09Z

    On Friday, October 24, 2025 11:22 PM vignesh C <vignesh21@gmail.com> wrote:
    > 
    > On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > The attached patch has the changes for the same.
    > > >
    > >
    > > I have pushed 0001 and the following are comments on 0002.
    > 
    > The attached v20251024 version patch has the changes for the same.
    > The comments from [1] have also been addressed in this version.
    
    Thanks for updating the patch.
    
    I was reviewing 0003 and have some thoughts for simplifying the codes related to
    sequence state invalidations and hash tables:
    
    1.  I'm considering whether we could lock sequences at the start and maintain
        these locks until the copy process finishes, allowing us to remove
        invalidation codes.
    
       I understand that the current process is:
    
       1. start a transaction to fetch namespace/seqname for all the sequences in
          the pg_subscription_rel
       2. start multiple transation and handle a batch of in each transaction
    
       So if there are sequence is altered between step 1 and 2, then we need to
       skip the renamed or dropped sequences in step 2 and invalidates the hash
       entry which looks inelegant.
    
       To improve this, my proposal is to postpone the namespace/seqname fetch logic
       until the second step. Initially, we would fetch just the sequence OIDs.
       Then, in step 2, we would fetch the namespace/seqname after locking the
       sequence. This approach ensures that any concurrent RENAME operations between
       steps are irrelevant, as we will use the latest sequence names to query the
       publisher, preventing any RENAME during step 2. This logic is also consistent
       with tablesync process where we lock the table first and get nspname/relname
       after that.
    
    2. We currently use a hash table to map remote sequence information to local
       sequence data. I'm exploring the possibility of using a List instead. By
       passing the sequence's index in the List to the query:
    
       The idea is to pass the index of the sequence in the List to the query like:
    
       "FROM ( VALUES %s ) AS s (schname, seqname, seqidx)"
    
       Upon receiving the results, we can directly map remote sequences to local
       ones using:: "list_nth(seqinfos, seqidx);"
    
    Here is a patch atop of 0003 that implements above ideas. Please take a
    look at this and see if it makes the code look better.
    
    Best Regards,
    Hou zj
    
  433. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-27T04:34:12Z

    On Mon, Oct 27, 2025 at 8:23 AM Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com>
    wrote:
    
    > On Friday, October 24, 2025 11:22 PM vignesh C <vignesh21@gmail.com>
    > wrote:
    > >
    > > On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com>
    > wrote:
    > > >
    > > > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com>
    > wrote:
    > > > >
    > > > > The attached patch has the changes for the same.
    > > > >
    > > >
    > > > I have pushed 0001 and the following are comments on 0002.
    > >
    >
    
    One question, I am not sure if this has been discussed before, So while
    getting sequence information from remote we are also getting the page_lsn
    of the sequence and we are storing that in pg_subscription_rel.  Is it just
    for the user to see and compare whether the sequence is synced to the
    latest lsn or is it used for anything else as well?  In our patch sert, I
    don't see much usability information about this field.
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
  434. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-27T06:41:11Z

    On Mon, Oct 27, 2025 at 10:04 AM Dilip Kumar <dilipbalaut@gmail.com> wrote:
    
    > On Mon, Oct 27, 2025 at 8:23 AM Zhijie Hou (Fujitsu) <
    > houzj.fnst@fujitsu.com> wrote:
    >
    >> On Friday, October 24, 2025 11:22 PM vignesh C <vignesh21@gmail.com>
    >> wrote:
    >> >
    >> > On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com>
    >> wrote:
    >> > >
    >> > > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com>
    >> wrote:
    >> > > >
    >> > > > The attached patch has the changes for the same.
    >> > > >
    >> > >
    >> > > I have pushed 0001 and the following are comments on 0002.
    >> >
    >>
    >
    > One question, I am not sure if this has been discussed before, So while
    > getting sequence information from remote we are also getting the page_lsn
    > of the sequence and we are storing that in pg_subscription_rel.  Is it just
    > for the user to see and compare whether the sequence is synced to the
    > latest lsn or is it used for anything else as well?  In our patch sert, I
    > don't see much usability information about this field.
    >
    
    Overall patch LGTM, and I really like the idea of getting rid of the hash
    and converting it into a list, now we don't need to restart the scan unlike
    hash due to transaction boundary.  However I have one more suggestion.
    
     /*
    + * Establish the connection to the publisher for sequence synchronization.
    + */
    + LogRepWorkerWalRcvConn =
    + walrcv_connect(MySubscription->conninfo, true, true,
    +   must_use_password,
    +   app_name.data, &err);
    + if (LogRepWorkerWalRcvConn == NULL)
    + ereport(ERROR,
    + errcode(ERRCODE_CONNECTION_FAILURE),
    + errmsg("sequencesync worker for subscription \"%s\" could not connect to
    the publisher: %s",
    +   MySubscription->name, err));
    +
    + pfree(app_name.data);
    +
    + /* If there are any sequences that need to be copied */
    + if (hash_get_num_entries(sequences_to_copy))
    + copy_sequences(LogRepWorkerWalRcvConn, subid);
    
    I think we should call 'walrcv_connect' only if we need to copy_sequences
    right?
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
  435. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-27T06:48:53Z

    On Mon, 27 Oct 2025 at 10:04, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    >
    > On Mon, Oct 27, 2025 at 8:23 AM Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> wrote:
    >>
    >> On Friday, October 24, 2025 11:22 PM vignesh C <vignesh21@gmail.com> wrote:
    >> >
    >> > On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >> > >
    >> > > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com> wrote:
    >> > > >
    >> > > > The attached patch has the changes for the same.
    >> > > >
    >> > >
    >> > > I have pushed 0001 and the following are comments on 0002.
    >> >
    >
    >
    > One question, I am not sure if this has been discussed before, So while getting sequence information from remote we are also getting the page_lsn of the sequence and we are storing that in pg_subscription_rel.  Is it just for the user to see and compare whether the sequence is synced to the latest lsn or is it used for anything else as well?  In our patch sert, I don't see much usability information about this field.
    
    This is mainly intended for the following purposes:  a) To determine
    whether the sequence requires resynchronization by comparing it with
    the latest LSN on the publisher b. ) To maintain consistency with
    table synchronization behavior.  c) To inform users up to which LSN
    the sequence has been synchronized.
    Further details will be documented in an upcoming patch.
    
    Regards,
    Vignesh
    
    
    
    
  436. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-27T08:29:41Z

    On Mon, Oct 27, 2025 at 8:23 AM Zhijie Hou (Fujitsu)
    <houzj.fnst@fujitsu.com> wrote:
    >
    > On Friday, October 24, 2025 11:22 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > The attached patch has the changes for the same.
    > > > >
    > > >
    > > > I have pushed 0001 and the following are comments on 0002.
    > >
    > > The attached v20251024 version patch has the changes for the same.
    > > The comments from [1] have also been addressed in this version.
    >
    > Thanks for updating the patch.
    >
    > I was reviewing 0003 and have some thoughts for simplifying the codes related to
    > sequence state invalidations and hash tables:
    >
    > 1.  I'm considering whether we could lock sequences at the start and maintain
    >     these locks until the copy process finishes, allowing us to remove
    >     invalidation codes.
    >
    >    I understand that the current process is:
    >
    >    1. start a transaction to fetch namespace/seqname for all the sequences in
    >       the pg_subscription_rel
    >    2. start multiple transation and handle a batch of in each transaction
    >
    >    So if there are sequence is altered between step 1 and 2, then we need to
    >    skip the renamed or dropped sequences in step 2 and invalidates the hash
    >    entry which looks inelegant.
    >
    >    To improve this, my proposal is to postpone the namespace/seqname fetch logic
    >    until the second step. Initially, we would fetch just the sequence OIDs.
    >    Then, in step 2, we would fetch the namespace/seqname after locking the
    >    sequence. This approach ensures that any concurrent RENAME operations between
    >    steps are irrelevant, as we will use the latest sequence names to query the
    >    publisher, preventing any RENAME during step 2. This logic is also consistent
    >    with tablesync process where we lock the table first and get nspname/relname
    >    after that.
    >
    > 2. We currently use a hash table to map remote sequence information to local
    >    sequence data. I'm exploring the possibility of using a List instead. By
    >    passing the sequence's index in the List to the query:
    >
    >    The idea is to pass the index of the sequence in the List to the query like:
    >
    >    "FROM ( VALUES %s ) AS s (schname, seqname, seqidx)"
    >
    >    Upon receiving the results, we can directly map remote sequences to local
    >    ones using:: "list_nth(seqinfos, seqidx);"
    >
    > Here is a patch atop of 0003 that implements above ideas. Please take a
    > look at this and see if it makes the code look better.
    >
    
    I like the overall idea here. With this approach, since we first fetch
    the relids and then retrieve the sequence names later (after taking
    the exclusive lock), our remote query will always use the latest
    names, whether they’re the original or altered ones, it doesn’t
    matter. The sequence name itself can’t change during this step, so
    we’re safe on that front. As a result, the race conditions I mentioned
    in [1] and [2] are no longer applicable. I’ll still go through the
    patch in more detail to verify and review it.
    
    [1]: https://www.postgresql.org/message-id/CAJpy0uC-Jx2L6tOTnDQ_Zwz99X3HQDik6tG%3D%2B1a71SxZFiy12w%40mail.gmail.com
    [2]: https://www.postgresql.org/message-id/CAJpy0uAQ43WjvuBi9F_hOJwsa1veGCJJs0ogH1o_o9AAv0jTfg%40mail.gmail.com
    
    thanks
    Shveta
    
    
    
    
  437. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-27T08:42:33Z

    On Sat, Oct 25, 2025 at 12:16 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Fri, Oct 24, 2025 at 11:43 AM shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > 5)
    > > For the race condition where the worker is going to access the seq
    > > locally and meanwhile it is altered; now the worker correctly reports
    > > this. But it reports this as a success scenario. And once the scenario
    > > is reported as 'seq-worker finished', we do not expect it to start
    > > running again without the user doing REFRESH. But in this case, it
    > > runs, see logs. Also it starts immediately for once due to the same
    > > reason that start_time is reset in the success scenario.
    > > -------
    > > 17:35:05.618 IST [132551] LOG:  logical replication apply worker for
    > > subscription "sub1" has started
    > > 17:35:05.637 IST [132553] LOG:  logical replication sequence
    > > synchronization worker for subscription "sub1" has started
    > > 17:35:05.663 IST [132553] LOG:  logical replication sequence
    > > synchronization for subscription "sub1" - total unsynchronized: 1
    > > 17:36:11.987 IST [132553] LOG:  skip synchronization of sequence
    > > "public.myseq249" because it has been altered concurrently
    > > 17:36:19.614 IST [132553] LOG:  logical replication sequence
    > > synchronization for subscription "sub1" - batch #1 = 1 attempted, 0
    > > succeeded, 1 skipped, 0 mismatched, 0 insufficient permission, 0
    > > missing from publisher
    > > 17:36:20.335 IST [132553] LOG:  logical replication sequence
    > > synchronization worker for subscription "sub1" has finished
    > > 17:36:20.435 IST [132586] LOG:  logical replication sequence
    > > synchronization worker for subscription "sub1" has started
    > > 17:36:20.545 IST [132586] LOG:  logical replication sequence
    > > synchronization for subscription "sub1" - total unsynchronized: 1
    > > -------
    > >
    > > The behaviour looks slightly odd. Is there anything we can do about
    > > this? Shall the skipped case be reported as ERROR due to the fact that
    > > we leave it in state 'i' in pg_subscription_rel?
    > >
    >
    > The downside of reporting an ERROR as soon as we can't sync values for
    > one of the sequences is that the other sequences which could be synced
    > won't get synced.
    
    Yes, I agree.
    
    > The other possibility is that we skip processing
    > such a sequence while copying sequences but at the end if there is any
    > pending sequence which is not synced, we raise an ERROR. If we do that
    > then we may need to give some generic ERROR because there could be
    > multiple such sequences. The other possibility is that we can give a
    > LOG message like "logical replication sequence sync worker for
    > subscription \"%s\" will restart because ..." and then do proc_exit(1)
    > without resetting restart_time. Will that help to address your
    > concern?
    >
    
    Thanks for suggesting these potential solutions. After reviewing the
    new approach proposed in [1] by Hou-San, I believe this race condition
    is no longer applicable, so we’re safe.
    
    [1]: https://www.postgresql.org/message-id/TY4PR01MB169078D0BB792F1EE438A2EE294FCA%40TY4PR01MB16907.jpnprd01.prod.outlook.com
    
    thanks
    Shveta
    
    
    
    
  438. Re: Logical Replication of sequences

    Chao Li <li.evan.chao@gmail.com> — 2025-10-27T09:11:46Z

    > On Oct 24, 2025, at 23:22, vignesh C <vignesh21@gmail.com> wrote:
    > 
    > Regards,
    > Vignesh
    > <v20251024-0001-Rename-sync_error_count-to-tbl_sync_error_.patch><v20251024-0002-Add-worker-type-argument-to-logicalrep_wor.patch><v20251024-0003-New-worker-for-sequence-synchronization-du.patch><v20251024-0004-Documentation-for-sequence-synchronization.patch>
    
    
    The changes in 0001 are straightforward, looks good. I haven’t reviewed 0004 yet. Got a few comments for 0002 and 0003.
    
    1 - 0002
    ```
      * We are only interested in the leader apply worker or table sync worker.
    + * For apply workers, the relid should be set to InvalidOid, as they manage
    + * changes across all tables and sequences. For table sync workers, the relid
    + * should be set to the OID of the relation being synchronized.
      */
     LogicalRepWorker *
    -logicalrep_worker_find(Oid subid, Oid relid, bool only_running)
    +logicalrep_worker_find(Oid subid, Oid relid, LogicalRepWorkerType wtype,
    +					   bool only_running)
     {
     	int			i;
     	LogicalRepWorker *res = NULL;
     
     	Assert(LWLockHeldByMe(LogicalRepWorkerLock));
    ```
    
    The comment says that “for apply workers, the relid should be set to InvalidOid”, so is it worthy adding an assert for that?
    
    2 - 0002
    ```
    -	/* Search for attached worker for a given subscription id. */
    +	/* Search for the attached worker matching the specified criteria. */
     	for (i = 0; i < max_logical_replication_workers; i++)
     	{
    ```
    
    Minor issue with the comment:
    
    * we are not search for a specific work, so “the” should be “a”
    * “attached” is confusing. In the old comment, ‘attached” tied to “a given subscription id”, but now, attach to what?
    
    So suggested revision:
    
    “/* Search for a logical replication worker matching the specified criteria */”
    
    3 - 0002
    ```
     /*
      * Stop the logical replication worker for subid/relid, if any.
    + *
    + * Similar to logicalrep_worker_find, relid should be set to a valid OID only
    + * for table sync workers.
      */
     void
    -logicalrep_worker_stop(Oid subid, Oid relid)
    +logicalrep_worker_stop(Oid subid, Oid relid, LogicalRepWorkerType wtype)
    ```
    
    The comment should be updated: subid/relid => subid/relid/wtype.
    
    4 - 0002
    ```
    @@ -477,7 +477,8 @@ ProcessSyncingTablesForApply(XLogRecPtr current_lsn)
     			LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
     
     			syncworker = logicalrep_worker_find(MyLogicalRepWorker->subid,
    -												rstate->relid, false);
    +												rstate->relid,
    +												WORKERTYPE_TABLESYNC, true);
    ```
    
    Why changed only_running from false to true? This commit adds a new worker type, but don’t tend to change the existing logic.
    
    5 - 0003
    ```
    +/*
    + * Reset the last_seqsync_start_time of the sequencesync worker in the
    + * subscription's apply worker.
    + */
    +void
    +logicalrep_reset_seqsync_start_time(void)
    +{
    +	LogicalRepWorker *worker;
    +
    +	LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
    +
    +	/*
    +	 * Set the last_seqsync_start_time for the sequence worker in the apply
    +	 * worker instead of the sequence sync worker, as the sequence sync worker
    +	 * has finished and is about to exit.
    +	 */
    +	worker = logicalrep_worker_find(MyLogicalRepWorker->subid, InvalidOid,
    +									WORKERTYPE_APPLY, true);
    +	if (worker)
    +		worker->last_seqsync_start_time = 0;
    +
    +	LWLockRelease(LogicalRepWorkerLock);
    +}
    ```
    
    Two comments for this new function:
    
    * The function comment and in-code comment are redundant. Suggesting move the in-code comment to function comment.
    * Why LW_SHARED is used? We are writing worker->last_seqsync_start_time, shouldn’t LW_EXCLUSIVE be used?
    
    6 - 0003
    ```
    +	/*
    +	 * Count running sync workers for this subscription, while we have the
    +	 * lock.
    +	 */
    +	nsyncworkers = logicalrep_sync_worker_count(MyLogicalRepWorker->subid);
    +	LWLockRelease(LogicalRepWorkerLock);
    +
    +	launch_sync_worker(nsyncworkers, InvalidOid,
    +					   &MyLogicalRepWorker->last_seqsync_start_time);
    ```
    
    I think here could be a race condition. Because the lock is acquired in LW_SHARED, meaning multiple caller may get the same nsyncworkers. Then it launches sync worker based on nsyncworkers, which would use inaccurate nsyncworkers, because between LWLockRelease() and launch_sync_worker(), another worker might be started.
    
    But if that is not the case, only one caller should call ProcessSyncingSequencesForApply(), then why the lock is needed?
    
    7 - 0003
    ```
    +	if (insuffperm_seqs->len)
    +	{
    +		appendStringInfo(combined_error_detail, "Insufficient permission for sequence(s): (%s)",
    +						 insuffperm_seqs->data);
    +		appendStringInfoString(combined_error_hint, "Grant permissions for the sequence(s).");
    +	}
    ```
    
    “Grant permissions” is unclear. Should it be “Grant UPDATE privilege”?
    
    8 - 0003
    ```
    +			appendStringInfoString(combined_error_hint, " For mismatched sequences, alter or re-create local sequences to have matching parameters as publishers.");
    ```
    
    “To have matching parameters as publishers” grammatically sound not good. Maybe revision to “to match the publisher’s parameters”.
    
    9 - 0003
    ```
    +		/*
    +		 * current_indexes is not incremented sequentially because some
    +		 * sequences may be missing, and the number of fetched rows may not
    +		 * match the batch size. The `hash_search` with HASH_REMOVE takes care
    +		 * of the count.
    +		 */
    ```
    
    Typo: current_indexes => current_index
    
    10 - 0003
    ```
    -	/* Find the leader apply worker and signal it. */
    -	logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    +	/*
    +	 * This is a clean exit of the sequencesync worker; reset the
    +	 * last_seqsync_start_time.
    +	 */
    +	if (wtype == WORKERTYPE_SEQUENCESYNC)
    +		logicalrep_reset_seqsync_start_time();
    +	else
    +		/* Find the leader apply worker and signal it. */
    +		logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    ```
    
    The comment “this is a clean exist of sequencsync worker” is specific to “if”, so suggesting moving into “if”. And “this is a clean exis of the sequencesyc worker” is not needed, keep consistent with the comment in “else”.
    
    11 - 0003
    ```
    +void
    +launch_sync_worker(int nsyncworkers, Oid relid, TimestampTz *last_start_time)
    +{
    +	/* If there is a free sync worker slot, start a new sync worker */
    +	if (nsyncworkers < max_sync_workers_per_subscription)
    +	{
    ```
    
    The entire function is under an “if”, so we can do “if (!…) return”, so saves a level of indent.
    
    Best regards,
    —
    Chao Li (Evan)
    HighGo Software Co., Ltd.
    https://www.highgo.com/
    
    
    
    
    
    
    
    
  439. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-27T11:40:19Z

    On Mon, Oct 27, 2025 at 12:19 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 27 Oct 2025 at 10:04, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > >
    > > On Mon, Oct 27, 2025 at 8:23 AM Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> wrote:
    > >>
    > >> On Friday, October 24, 2025 11:22 PM vignesh C <vignesh21@gmail.com> wrote:
    > >> >
    > >> > On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >> > >
    > >> > > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com> wrote:
    > >> > > >
    > >> > > > The attached patch has the changes for the same.
    > >> > > >
    > >> > >
    > >> > > I have pushed 0001 and the following are comments on 0002.
    > >> >
    > >
    > >
    > > One question, I am not sure if this has been discussed before, So while getting sequence information from remote we are also getting the page_lsn of the sequence and we are storing that in pg_subscription_rel.  Is it just for the user to see and compare whether the sequence is synced to the latest lsn or is it used for anything else as well?  In our patch sert, I don't see much usability information about this field.
    >
    > This is mainly intended for the following purposes:  a) To determine
    > whether the sequence requires resynchronization by comparing it with
    > the latest LSN on the publisher b. ) To maintain consistency with
    > table synchronization behavior.  c) To inform users up to which LSN
    > the sequence has been synchronized.
    > Further details will be documented in an upcoming patch.
    >
    
    Can we use it to build an auto-sequence-sync feature? One can imagine
    that at some threshold interval apply_worker can check if any of the
    replicated sequences are out-of-sync and if so, then sync those. We
    can do this before the apply_worker waits for some activity or on a
    clean shutdown. That way users won't need to manually sync these
    sequences before upgrade.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  440. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-27T11:44:54Z

    On Sat, 25 Oct 2025 at 12:27, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Fri, Oct 24, 2025 at 8:52 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > The attached patch has the changes for the same.
    > > > >
    > > >
    > > > I have pushed 0001 and the following are comments on 0002.
    > > >
    > > > 1.
    > > > @@ -1414,6 +1414,7 @@ CREATE VIEW pg_stat_subscription_stats AS
    > > >          ss.subid,
    > > >          s.subname,
    > > >          ss.apply_error_count,
    > > > +        ss.sequence_sync_error_count,
    > > >          ss.sync_error_count,
    > > >
    > > > The new parameter name is noticeably longer than other columns. Can we
    > > > name it as ss.seq_sync_error_count. We may also want to reconsider
    > > > changing existing column sync_error_count to tbl_sync_error_count. Can
    > > > we extract this in a separate stats patch?
    > >
    > > Modified and extracted a separate patch for tbl_sync_error_count
    > >
    >
    > Hmm, I didn't want to make the stats related changes before the main
    > patch. I suggested to extract seq_sync_error_count from the main patch
    > and keep it after the main patch.
    
    Made this change.
    
    > Along with the seq_sync_error_count
    > stats, we can discuss whether to change existing parameter to
    > tbl_sync_error_count.
    
    I have removed the tbl_sync_error_count changes for now, I will add it
    if required when we get to that patch.
    
    This version also addresses Chao's comments on 0002 which he posted at [1].
    The attached patch has the changes for the same.
    
    [1] - https://www.postgresql.org/message-id/BABE39BA-6893-4D65-8432-5523960FFC2B%40gmail.com
    
    Regards,
    Vignesh
    
  441. Re: Logical Replication of sequences

    Chao Li <li.evan.chao@gmail.com> — 2025-10-28T01:47:03Z

    
    > On Oct 27, 2025, at 17:11, Chao Li <li.evan.chao@gmail.com> wrote:
    > 
    > The changes in 0001 are straightforward, looks good. I haven’t reviewed 0004 yet. 
    
    Comments for 0004:
    
    1 - config.sgml
    ```
    -        In logical replication, this parameter also limits how often a failing
    -        replication apply worker or table synchronization worker will be
    -        respawned.
    +        In logical replication, this parameter also limits how quickly a
    +        failing replication apply worker, table synchronization worker, or
    +        sequence synchronization worker will be respawned.
    ```
    
    * “a failing replication apply worker” sounds a bit redundant, maybe change to “a failed apply worker”
    * “will be respawned” works, but in formal documentation, I think “is respawned” is better
    
    2 - logic-replication.sgml
    ```
    -   or <literal>FOR ALL SEQUENCES</literal>.
    +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    +   sequences may be synchronized at any time. For more information, refer to
    +   <xref linkend="logical-replication-sequences"/>.
    ```
    
    * “may be” better to be “can be”
    * I think the first sentence can be slightly enhanced as "Unlike tables, the state of a sequence can be synchronized at any time.”
    * “refer to” should be “see” in PG docs. You can see right the next paragraph just uses “see”:
    ```
    <command>TRUNCATE</command>. See <xref linkend="logical-replication-row-filter"/>).
    ```
    
    3 - logic-replication.sgml
    ```
    +   To synchronize sequences from a publisher to a subscriber, first publish
    +   them using <link linkend="sql-createpublication-params-for-all-sequences">
    +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link> and then
    +   at the subscriber side:
    ```
    
    “At the subscriber side” is better to be “on the subscriber”. Actually, you also use “on the subscriber” in the following paragraphs.
    
    4 - logic-replication.sgml
    ```
        During sequence synchronization, the sequence definitions of the publisher
        and the subscriber are compared. An ERROR is logged listing all differing
        sequences before the process exits. The apply worker detects this failure
        and repeatedly respawns the sequence synchronization worker to continue
        the synchronization process until all differences are resolved. See also
    ```
    
    * “An ERROR” => “An error”. If you search for the current doc, “error” are all in lower case.
    * " the sequence synchronization worker to continue the synchronization process”, the second “synchronization” sounds redundant, maybe enhance to "the sequence synchronization worker to retry"
    
    5 - logic-replication.sgml
    ```
        During sequence synchronization, if a sequence is dropped on the
        publisher, the sequence synchronization worker will identify this and
        remove it from sequence synchronization on the subscriber.
    ```
    
    “Will identify this” => “detects the change”, I think PG docs usually prefer more direct phrasing.
    
    Best regards,
    --
    Chao Li (Evan)
    HighGo Software Co., Ltd.
    https://www.highgo.com/
    
    
    
    
    
    
    
    
  442. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-28T04:26:17Z

    Hi Vignesh,
    
    WIP - Some comments for patch v20251027-0003
    
    ======
    General.
    
    1.
    When referring to synchronization workers AFAIK the convention has always been:
    
    - code/comments refer to "tablesync workers" and "sequencesync workers"
    - but errors/docs mostly use the long form like "table synchronization
    workers" and "sequence synchronization workers"
    
    This patch still has places saying "sequence sync worker" instead of
    "sequencesync worker" etc. IMO these should be changed, otherwise
    there are too many variations of saying the same thing.
    
    ======
    src/backend/commands/sequence.c
    
    pg_get_sequence_data:
    
    2.
    /*
    * See the comment in copy_sequence() above
    * UpdateSubscriptionRelState() for details on recording the LSN.
    */
    
    Consider rewording that more like:
    For details about recording the LSN, see the
    UpdateSubscriptionRelState() call in copy_sequence().
    
    ======
    src/backend/replication/logical/launcher.c
    
    logicalrep_worker_find:
    
    3.
    /sequence sync workers/sequencesync workers/
    /table sync workers/tablesync workers/
    
    ~~~
    
    logicalrep_reset_seqsync_start_time:
    
    4.
    + /*
    + * Set the last_seqsync_start_time for the sequence worker in the apply
    + * worker instead of the sequence sync worker, as the sequence sync worker
    + * has finished and is about to exit.
    + */
    
    Half of this comment was already described in the function comment.
    Maybe better to remove this comment, and instead just add more to the
    function comment.
    
    SUGGESTION (function comment)
    Reset the last_seqsync_start_time of the sequencesync worker in the
    subscription's apply worker. Note -- this value is not stored in the
    sequencesync worker, because that has finished already and is about to
    exit.
    
    ======
    src/backend/replication/logical/syncutils.c
    
    FinishSyncWorker:
    
    5.
    +FinishSyncWorker()
     {
    + LogicalRepWorkerType wtype = MyLogicalRepWorker->type;
    +
    + Assert(wtype == WORKERTYPE_TABLESYNC || wtype == WORKERTYPE_SEQUENCESYNC);
    +
    
    We already have some macros so I think it's better to make use of them
    
    SUGGESTION
    
    Assert(am_tablesync_worker() || am_sequencesync_worker())
    
    ~
    
    Similarly, the subsequent code like:
    
    + if (wtype == WORKERTYPE_TABLESYNC)
    and
    + if (wtype == WORKERTYPE_SEQUENCESYNC)
    
    becomes
    if (am_tablesync_worker()) ...
    if (am_sequencesync_worker()) ...
    
    ~~~
    
    6.
    + /*
    + * This is a clean exit of the sequencesync worker; reset the
    + * last_seqsync_start_time.
    + */
    + if (wtype == WORKERTYPE_SEQUENCESYNC)
    + logicalrep_reset_seqsync_start_time();
    + else
    + /* Find the leader apply worker and signal it. */
    + logicalrep_worker_wakeup(WORKERTYPE_APPLY, MyLogicalRepWorker->subid,
    + InvalidOid);
    
    I think those comments belong within the if blocks, so add some {}
    
    SUGGESTION
    
    if (is_sequencesync)
    {
    /* comment ... */
    logicalrep_reset_seqsync_start_time(...)
    }
    else
    {
    /* comment ... */
    logicalrep_worker_wakeup(...)
    }
    
    ~~~
    
    launch_sync_worker:
    
    7.
     /*
    - * Process possible state change(s) of relations that are being synchronized.
    + * Attempt to launch a sync worker (sequence or table) if there is a sync
    + * worker slot available and the retry interval has elapsed.
    + *
    + * nsyncworkers: Number of currently running sync workers for the subscription.
    + * relid:  InvalidOid for sequence sync worker, actual relid for table sync
    + * worker.
    + * last_start_time: Pointer to the last start time of the worker.
    + */
    
    /sequence sync worker/sequencesync worker/
    /table sync worker/tablesync worker/
    
    ~~~
    
    8.
    + (void) logicalrep_worker_launch((relid == InvalidOid) ?
    WORKERTYPE_SEQUENCESYNC : WORKERTYPE_TABLESYNC,
    
    Tidier to use macro:
    OidIsValid(relid) ? WORKERTYPE_TABLESYNC : WORKERTYPE_SEQUENCESYNC
    
    OTOH, I think the caller already knows the WORKERTYPE_xxx it is
    launching, perhaps it is best to pass 'wtype' as another  parameter to
    launch_sync_worker()?
    
    ~~~
    
    FetchRelationStates
    
    9.
    + /*
    + * has_subtables and has_subsequences_non_ready is declared as static,
    + * since the same value can be used until the system table is invalidated.
    + */
    
    typo: /is declared/are declared/
    
    ======
    src/backend/replication/logical/worker.c
    
    DisableSubscriptionAndExit:
    
    10.
    + LogicalRepWorkerType wtype = am_tablesync_worker() ? WORKERTYPE_TABLESYNC :
    + (am_sequencesync_worker()) ? WORKERTYPE_SEQUENCESYNC :
    + WORKERTYPE_APPLY;
    +
    
    Why is this code needed at all?
    
    I think we don't need wtype, because later code that says:
    + if (wtype != WORKERTYPE_SEQUENCESYNC)
    
    Can instead just say:
    + if (am_apply_worker() || am_tablesync_worker())
    
    ======
    src/include/catalog/pg_subscription_rel.h
    
    11.
    +typedef struct LogicalRepSeqHashKey
    +{
    + const char *seqname;
    + const char *nspname;
    +} LogicalRepSeqHashKey;
    +
    +typedef struct LogicalRepSequenceInfo
    +{
    + char    *seqname;
    + char    *nspname;
    + Oid localrelid;
    + bool remote_seq_queried;
    + Oid seqowner;
    + bool entry_valid;
    +} LogicalRepSequenceInfo;
    
    No comments?
    
    ======
    src/include/commands/sequence.h
    
    12.
    +#define SEQ_LOG_CNT_INVALID 0
    +
    
    Unused?
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  443. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-28T06:04:15Z

    On Mon, Oct 27, 2025 at 5:10 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Mon, Oct 27, 2025 at 12:19 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Mon, 27 Oct 2025 at 10:04, Dilip Kumar <dilipbalaut@gmail.com> wrote:
    > > >
    > > >
    > > > One question, I am not sure if this has been discussed before, So while getting sequence information from remote we are also getting the page_lsn of the sequence and we are storing that in pg_subscription_rel.  Is it just for the user to see and compare whether the sequence is synced to the latest lsn or is it used for anything else as well?  In our patch sert, I don't see much usability information about this field.
    > >
    > > This is mainly intended for the following purposes:  a) To determine
    > > whether the sequence requires resynchronization by comparing it with
    > > the latest LSN on the publisher b. ) To maintain consistency with
    > > table synchronization behavior.  c) To inform users up to which LSN
    > > the sequence has been synchronized.
    > > Further details will be documented in an upcoming patch.
    > >
    >
    > Can we use it to build an auto-sequence-sync feature? One can imagine
    > that at some threshold interval apply_worker can check if any of the
    > replicated sequences are out-of-sync and if so, then sync those. We
    > can do this before the apply_worker waits for some activity or on a
    > clean shutdown.
    >
    
    We can even consider letting sequence sync worker do this by not
    exiting it after syncing all required sequences. Having said that,
    even if this is feasible, we should consider it as a top-up patch
    after the sequence sync worker patch is committed.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  444. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-28T10:03:48Z

    On Mon, Oct 27, 2025 at 8:23 AM Zhijie Hou (Fujitsu)
    <houzj.fnst@fujitsu.com> wrote:
    >
    > On Friday, October 24, 2025 11:22 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Thu, 23 Oct 2025 at 16:47, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Thu, Oct 23, 2025 at 11:45 AM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > The attached patch has the changes for the same.
    > > > >
    > > >
    > > > I have pushed 0001 and the following are comments on 0002.
    > >
    > > The attached v20251024 version patch has the changes for the same.
    > > The comments from [1] have also been addressed in this version.
    >
    > Thanks for updating the patch.
    >
    > I was reviewing 0003 and have some thoughts for simplifying the codes related to
    > sequence state invalidations and hash tables:
    >
    > 1.  I'm considering whether we could lock sequences at the start and maintain
    >     these locks until the copy process finishes, allowing us to remove
    >     invalidation codes.
    >
    >    I understand that the current process is:
    >
    >    1. start a transaction to fetch namespace/seqname for all the sequences in
    >       the pg_subscription_rel
    >    2. start multiple transation and handle a batch of in each transaction
    >
    >    So if there are sequence is altered between step 1 and 2, then we need to
    >    skip the renamed or dropped sequences in step 2 and invalidates the hash
    >    entry which looks inelegant.
    >
    >    To improve this, my proposal is to postpone the namespace/seqname fetch logic
    >    until the second step. Initially, we would fetch just the sequence OIDs.
    >    Then, in step 2, we would fetch the namespace/seqname after locking the
    >    sequence. This approach ensures that any concurrent RENAME operations between
    >    steps are irrelevant, as we will use the latest sequence names to query the
    >    publisher, preventing any RENAME during step 2.
    >
    
    I think this can lead to undetected deadlock for operations across
    nodes. Consider the following example: Say on each node, we have an
    AlterSequence operation being performed by a concurrent backend in the
    form below.
    
    On Node-1:
    ----------------
    Begin
    step-1
    sequence sync worker: copy_sequences, locked sequence (say seq-1) in
    RowExclusive mode;
    
    Begin;
    step-2
    Alter Sequence seq-1... --step-2 wait on step-1
    
    step-3
    Query on pg_get_sequence_data (from Node-2) will wait for Alter
    Sequence. --step-3 wait on step-2
    
    On Node-2:
    ----------------
    Begin;
    step-1
    sequence sync worker: copy_sequences, locked sequence (say seq-1) in
    RowExclusive mode;
    
    Begin
    step-2
    Alter Sequence seq-1 ... -- step-2 wait on step-1
    
    step-3
    Query on pg_get_sequence_data (from Node-1) will wait for Alter
    Sequence. --step-3 wait on step-2
    
    If the above scenario is possible then the two nodes will create a
    deadlock which can't be detected.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  445. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-28T12:30:16Z

    On Mon, 27 Oct 2025 at 14:42, Chao Li <li.evan.chao@gmail.com> wrote:
    >
    >
    > > On Oct 24, 2025, at 23:22, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > Regards,
    > > Vignesh
    > > <v20251024-0001-Rename-sync_error_count-to-tbl_sync_error_.patch><v20251024-0002-Add-worker-type-argument-to-logicalrep_wor.patch><v20251024-0003-New-worker-for-sequence-synchronization-du.patch><v20251024-0004-Documentation-for-sequence-synchronization.patch>
    >
    >
    > The changes in 0001 are straightforward, looks good. I haven’t reviewed 0004 yet. Got a few comments for 0002 and 0003.
    
    > 5 - 0003
    > ```
    > +/*
    > + * Reset the last_seqsync_start_time of the sequencesync worker in the
    > + * subscription's apply worker.
    > + */
    > +void
    > +logicalrep_reset_seqsync_start_time(void)
    > +{
    > +       LogicalRepWorker *worker;
    > +
    > +       LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
    > +
    > +       /*
    > +        * Set the last_seqsync_start_time for the sequence worker in the apply
    > +        * worker instead of the sequence sync worker, as the sequence sync worker
    > +        * has finished and is about to exit.
    > +        */
    > +       worker = logicalrep_worker_find(MyLogicalRepWorker->subid, InvalidOid,
    > +                                                                       WORKERTYPE_APPLY, true);
    > +       if (worker)
    > +               worker->last_seqsync_start_time = 0;
    > +
    > +       LWLockRelease(LogicalRepWorkerLock);
    > +}
    > ```
    >
    > Two comments for this new function:
    >
    > * The function comment and in-code comment are redundant. Suggesting move the in-code comment to function comment.
    > * Why LW_SHARED is used? We are writing worker->last_seqsync_start_time, shouldn’t LW_EXCLUSIVE be used?
    
    There will be only one sequence sync worker and only this process is
    going to update this, so LW_SHARED is enough to find the apply worker.
    
    > 6 - 0003
    > ```
    > +       /*
    > +        * Count running sync workers for this subscription, while we have the
    > +        * lock.
    > +        */
    > +       nsyncworkers = logicalrep_sync_worker_count(MyLogicalRepWorker->subid);
    > +       LWLockRelease(LogicalRepWorkerLock);
    > +
    > +       launch_sync_worker(nsyncworkers, InvalidOid,
    > +                                          &MyLogicalRepWorker->last_seqsync_start_time);
    > ```
    >
    > I think here could be a race condition. Because the lock is acquired in LW_SHARED, meaning multiple caller may get the same nsyncworkers. Then it launches sync worker based on nsyncworkers, which would use inaccurate nsyncworkers, because between LWLockRelease() and launch_sync_worker(), another worker might be started.
    >
    > But if that is not the case, only one caller should call ProcessSyncingSequencesForApply(), then why the lock is needed?
    
    Sequence sync worker will be started only by the apply worker, another
    worker cannot be started for this subscription between LWLockRelease()
    and launch_sync_worker() as this apply worker is responsible for it
    and the apply worker is active with current work. Same logic is used
    for table sync workers too.
    
    > 7 - 0003
    > ```
    > +       if (insuffperm_seqs->len)
    > +       {
    > +               appendStringInfo(combined_error_detail, "Insufficient permission for sequence(s): (%s)",
    > +                                                insuffperm_seqs->data);
    > +               appendStringInfoString(combined_error_hint, "Grant permissions for the sequence(s).");
    > +       }
    > ```
    >
    > “Grant permissions” is unclear. Should it be “Grant UPDATE privilege”?
    
    Modified
    
    > 8 - 0003
    > ```
    > +                       appendStringInfoString(combined_error_hint, " For mismatched sequences, alter or re-create local sequences to have matching parameters as publishers.");
    > ```
    >
    > “To have matching parameters as publishers” grammatically sound not good. Maybe revision to “to match the publisher’s parameters”.
    
    Modified
    
    > 9 - 0003
    > ```
    > +               /*
    > +                * current_indexes is not incremented sequentially because some
    > +                * sequences may be missing, and the number of fetched rows may not
    > +                * match the batch size. The `hash_search` with HASH_REMOVE takes care
    > +                * of the count.
    > +                */
    > ```
    >
    > Typo: current_indexes => current_index
    
    Modified
    
    > 10 - 0003
    > ```
    > -       /* Find the leader apply worker and signal it. */
    > -       logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    > +       /*
    > +        * This is a clean exit of the sequencesync worker; reset the
    > +        * last_seqsync_start_time.
    > +        */
    > +       if (wtype == WORKERTYPE_SEQUENCESYNC)
    > +               logicalrep_reset_seqsync_start_time();
    > +       else
    > +               /* Find the leader apply worker and signal it. */
    > +               logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    > ```
    >
    > The comment “this is a clean exist of sequencsync worker” is specific to “if”, so suggesting moving into “if”. And “this is a clean exis of the sequencesyc worker” is not needed, keep consistent with the comment in “else”.
    
    Modified
    
    > 11 - 0003
    > ```
    > +void
    > +launch_sync_worker(int nsyncworkers, Oid relid, TimestampTz *last_start_time)
    > +{
    > +       /* If there is a free sync worker slot, start a new sync worker */
    > +       if (nsyncworkers < max_sync_workers_per_subscription)
    > +       {
    > ```
    >
    > The entire function is under an “if”, so we can do “if (!…) return”, so saves a level of indent.
    
    Modified
    
    Peter's comments from [1] have also been addressed. The attached
    v20251029 version patch has the changes for the same.
    
    [1] - https://www.postgresql.org/message-id/CAHut%2BPtMc1fr6cQvUAnxRE%2Bbuim5m-d9M2dM0YAeEHNkS9KzBw%40mail.gmail.com
    
    Regards,
    Vignesh
    
  446. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-28T12:51:04Z

    On Tue, 28 Oct 2025 at 07:17, Chao Li <li.evan.chao@gmail.com> wrote:
    >
    >
    >
    > > On Oct 27, 2025, at 17:11, Chao Li <li.evan.chao@gmail.com> wrote:
    > >
    > > The changes in 0001 are straightforward, looks good. I haven’t reviewed 0004 yet.
    >
    > Comments for 0004:
    >
    > 1 - config.sgml
    > ```
    > -        In logical replication, this parameter also limits how often a failing
    > -        replication apply worker or table synchronization worker will be
    > -        respawned.
    > +        In logical replication, this parameter also limits how quickly a
    > +        failing replication apply worker, table synchronization worker, or
    > +        sequence synchronization worker will be respawned.
    > ```
    >
    > * “a failing replication apply worker” sounds a bit redundant, maybe change to “a failed apply worker”
    > * “will be respawned” works, but in formal documentation, I think “is respawned” is better
    
    I felt this was documented that way in the HEAD too, I prefer the one in HEAD.
    
    > 2 - logic-replication.sgml
    > ```
    > -   or <literal>FOR ALL SEQUENCES</literal>.
    > +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the current state of
    > +   sequences may be synchronized at any time. For more information, refer to
    > +   <xref linkend="logical-replication-sequences"/>.
    > ```
    >
    > * “may be” better to be “can be”
    > * I think the first sentence can be slightly enhanced as "Unlike tables, the state of a sequence can be synchronized at any time.”
    > * “refer to” should be “see” in PG docs. You can see right the next paragraph just uses “see”:
    > ```
    > <command>TRUNCATE</command>. See <xref linkend="logical-replication-row-filter"/>).
    > ```
    
    Modified
    
    > 3 - logic-replication.sgml
    > ```
    > +   To synchronize sequences from a publisher to a subscriber, first publish
    > +   them using <link linkend="sql-createpublication-params-for-all-sequences">
    > +   <command>CREATE PUBLICATION ... FOR ALL SEQUENCES</command></link> and then
    > +   at the subscriber side:
    > ```
    >
    > “At the subscriber side” is better to be “on the subscriber”. Actually, you also use “on the subscriber” in the following paragraphs.
    
    Modified
    
    > 4 - logic-replication.sgml
    > ```
    >     During sequence synchronization, the sequence definitions of the publisher
    >     and the subscriber are compared. An ERROR is logged listing all differing
    >     sequences before the process exits. The apply worker detects this failure
    >     and repeatedly respawns the sequence synchronization worker to continue
    >     the synchronization process until all differences are resolved. See also
    > ```
    >
    > * “An ERROR” => “An error”. If you search for the current doc, “error” are all in lower case.
    > * " the sequence synchronization worker to continue the synchronization process”, the second “synchronization” sounds redundant, maybe enhance to "the sequence synchronization worker to retry"
    
    Modified
    
    > 5 - logic-replication.sgml
    > ```
    >     During sequence synchronization, if a sequence is dropped on the
    >     publisher, the sequence synchronization worker will identify this and
    >     remove it from sequence synchronization on the subscriber.
    > ```
    >
    > “Will identify this” => “detects the change”, I think PG docs usually prefer more direct phrasing.
    
    This behavior has been changed now, I have removed it.
    
    These changes are available in the v20251029 version posted at [1].
    [1] -  https://www.postgresql.org/message-id/CAHut%2BPtMc1fr6cQvUAnxRE%2Bbuim5m-d9M2dM0YAeEHNkS9KzBw%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  447. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-29T02:47:04Z

    Hi Vignesh,
    
    Some more review comments for v20251029-0001.
    
    ======
    .../replication/logical/sequencesync.c
    
    1.
    + * The apply worker periodically scans pg_subscription_rel for sequences in
    + * INIT state. When such sequences are found, it spawns a
    + * sequencesync worker to handle synchronization.
    
    I did not see anything in this header comment that says there is
    currently no more than 1 sequencesync worker. The above part of the
    comment doesn't make that clear.
    
    ~~~
    
    2.
    + * Handle sequence synchronization cooperation from the apply worker.
    
    Is it simpler just to say:
    Apply worker determines if sequence synchronization is needed.
    
    ~~~
    
    report_error_sequences:
    
    3.
    +static void
    +report_error_sequences(StringInfo insuffperm_seqs, StringInfo mismatched_seqs,
    +    StringInfo missing_seqs)
    
    Function name seems strange. How about 'ereport_sequence_errors'?
    
    ~~~
    
    4.
    + if (mismatched_seqs->len)
    + {
    + if (insuffperm_seqs->len)
    + {
    + appendStringInfo(combined_error_detail, "; mismatched sequence(s) on
    subscriber: (%s)",
    + mismatched_seqs->data);
    + appendStringInfoString(combined_error_hint, " For mismatched
    sequences, alter or re-create local sequences to match the publisher's
    parameters.");
    + }
    + else
    + {
    + appendStringInfo(combined_error_detail, "Mismatched sequence(s) on
    subscriber: (%s)",
    + mismatched_seqs->data);
    + appendStringInfoString(combined_error_hint, "For mismatched
    sequences, alter or re-create local sequences to match the publisher's
    parameters.");
    + }
    + }
    +
    + if (missing_seqs->len)
    + {
    + if (insuffperm_seqs->len || mismatched_seqs->len)
    + {
    + appendStringInfo(combined_error_detail, "; missing sequence(s) on
    publisher: (%s)",
    + missing_seqs->data);
    + appendStringInfoString(combined_error_hint, " For missing sequences,
    remove them locally or run ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    to refresh the subscription.");
    + }
    + else
    + {
    + appendStringInfo(combined_error_detail, "Missing sequence(s) on
    publisher: (%s)",
    + missing_seqs->data);
    + appendStringInfoString(combined_error_hint, "For missing sequences,
    remove them locally or run ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    to refresh the subscription.");
    + }
    + }
    
    
    This logic has a lot of duplication just to handle the separate
    multiple details/hints. I think it can be simplified a lot.
    
    SUGGESTION
    if (mismatched_seqs->len)
    {
      if (combined_error_detail->len)
      {
        appendStringInfo(combined_error_detail, "; ");
        appendStringInfoChar(combined_error_hint, ' ');
      }
      appendStringInfo(combined_error_detail, "Mismatched sequence(s) ...);
      appendStringInfoString(combined_error_hint, "For mismatched sequences, ...);
    }
    if (missing_seqs->len)
    {
      if (combined_error_detail->len)
      {
        appendStringInfo(combined_error_detail, "; ");
        appendStringInfoChar(combined_error_hint, ' ');
      }
      appendStringInfo(combined_error_detail, "Missing sequence(s) on ...);
      appendStringInfoString(combined_error_hint, "For missing sequences,
    remove ...);
    }
    
    ~~~
    
    get_remote_sequence_info:
    
    5.
    +static void
    +get_remote_sequence_info(TupleTableSlot *slot, LogicalRepSeqHashKey *key,
    + int64 *last_value, bool *is_called,
    + XLogRecPtr *page_lsn, Oid *remote_typid,
    + int64 *remote_start, int64 *remote_increment,
    + int64 *remote_min, int64 *remote_max,
    + bool *remote_cycle)
    
    I felt this code might be better if you would introduce a new
    structure (or add to an existing one?) to hold all the members instead
    of declaring a dozen variables and passing them as parameters. So, a
    cleaner function signature here might be like:
    
    static SequenceInfo get_remote_sequence_info(TupleTableSlot *slot).
    
    This may also allow you to simplify other code that passes so many
    members as parameters -- e.g. also the validation function.
    
    ~~~
    validate_sequence:
    
    6.
    + /* Sequence was concurrently dropped */
    + if (!sequence_rel)
    + return COPYSEQ_SKIPPED;
    +
    + /* Sequence was concurrently dropped */
    + tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    + if (!HeapTupleIsValid(tup))
    + return COPYSEQ_SKIPPED;
    +
    + /* Sequence was concurrently invalidated */
    + if (!seqinfo->entry_valid)
    + {
    + ReleaseSysCache(tup);
    + return COPYSEQ_SKIPPED;
    + }
    
    6a.
    All those comments might be better written as questions. e.g.
    /* Sequence was concurrently dropped? */
    /* Sequence was concurrently dropped? */
    /* Sequence was concurrently invalidated? */
    
    ~
    
    6b.
    + /* Sequence was concurrently dropped */
    + tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    + if (!HeapTupleIsValid(tup))
    + return COPYSEQ_SKIPPED;
    
    I think the 2nd comment belongs after the tup assignment.
    
    ~
    
    6c.
    + local_seq = (Form_pg_sequence) GETSTRUCT(tup);
    + if (local_seq->seqtypid != remote_typid ||
    + local_seq->seqstart != remote_start ||
    + local_seq->seqincrement != remote_increment ||
    + local_seq->seqmin != remote_min ||
    + local_seq->seqmax != remote_max ||
    + local_seq->seqcycle != remote_cycle)
    + result = COPYSEQ_MISMATCH;
    
    This should have a comment like the others. e.g.
    /* Sequence parameters for remote/local are the same? */
    
    ~~~
    
    copy_sequence:
    
    7.
    +/*
    + * Apply remote sequence state to local sequence and mark it as synchronized.
    + */
    
    Is it better to explicitly name the state here too? e.g.
    
    /and mark it as synchronized/and mark it as synchronized (READY)/
    
    ~~~
    
    8.
    + /*
    + * Make sure that the sequence is copied as table owner, unless the user
    + * has opted out of that behaviour.
    + */
    + if (!MySubscription->runasowner)
    + SwitchToUntrustedUser(seqinfo->seqowner, &ucxt);
    
    8a.
    Is "table owner" the correct term here?
    
    ~
    
    8b.
    Why not use the 'run_as_owner' variable?
    
    ~~~
    
    copy_sequences:
    
    9.
    + ereport(ERROR,
    + errcode(ERRCODE_CONNECTION_FAILURE),
    + errmsg("could not receive list of sequence information from the
    publisher: %s",
    +    res->err));
    
    How about just:
    "could not fetch sequence information from the publisher: %s",
    
    ~~~
    
    10.
    + CopySeqResult result;
    
    'result' seems a slightly meaningless variable name since this is not
    even returned from the function.
    
    ~~~
    
    sequencesync_list_invalidate_cb:
    
    11.
    + if (reloid != InvalidOid)
    
    Use macro !OidIsValid(reloid)
    
    ~
    
    12.
    + hash_seq_init(&status, sequences_to_copy);
    +
    
    This init is common for the if/else so could be done outside.
    
    ~~~
    
    LogicalRepSeqMatchFunc:
    
    13.
    + /* Compare by namespace name first */
    + cmp = strcmp(k1->nspname, k2->nspname);
    + if (cmp != 0)
    + return cmp;
    +
    + /* If namespace names are equal, compare by sequence name */
    + return strcmp(k1->seqname, k2->seqname);
    
    A simpler way to write this comparator might look like:
    
    /* Compare by namespace name first, then by sequence name */
    cmp = strcmp(k1->nspname, k2->nspname);
    if (cmp == 0)
      cmp = strcmp(k1->seqname, k2->seqname);
    
    return cmp;
    
    ~~~
    
    LogicalRepSyncSequences:
    
    14.
    +/*
    + * Start syncing the sequences in the sequencesync worker.
    + */
    +static void
    +LogicalRepSyncSequences(void)
    
    Might need a different function comment. This one seems almost the
    same as the function comment for copy_sequences().
    
    ~~~
    
    15.
    + key.seqname = RelationGetRelationName(sequence_rel);
    + key.nspname = get_namespace_name(RelationGetNamespace(sequence_rel));
    +
    + /* Allocate the tracking info in a permanent memory context. */
    + oldctx = MemoryContextSwitchTo(CacheMemoryContext);
    +
    + seq_entry = hash_search(sequences_to_copy, &key, HASH_ENTER, &found);
    + Assert(!found);
    +
    + memset(seq_entry, 0, sizeof(LogicalRepSequenceInfo));
    +
    + seq_entry->localrelid = subrel->srrelid;
    + seq_entry->remote_seq_queried = false;
    + seq_entry->seqowner = sequence_rel->rd_rel->relowner;
    + seq_entry->entry_valid = true;
    
    Nit. It seems more natural to put the nspname before the seqname.
    
    So,
    key.nspname = ...
    key.seqname = ...
    
    and
    seq_entry->nspname = pstrdup(key.nspname);
    seq_entry->seqname = pstrdup(key.seqname);
    
    ~~~
    
    LogicalRepSyncSequences:
    
    16.
    + /* If there are any sequences that need to be copied */
    + if (hash_get_num_entries(sequences_to_copy))
    + copy_sequences(LogRepWorkerWalRcvConn, subid);
    
    If there are no sequences to copy then AFAICT (from
    SequenceSyncWorkerMain) this sequencesync worker is just going to just
    stop and exit isn't it? So, why didn't we check this earlier and
    perhaps could have avoided making a publisher connection
    LogRepWorkerWalRcvConn for no reason?
    
    ======
    src/backend/replication/logical/syncutils.c
    
    FinishSyncWorker:
    
    17.
    + if (am_tablesync_worker())
    + ereport(LOG,...));
    + else
    + ereport(LOG,...);
    
    + if (am_sequencesync_worker())
    + {
    ...
    + }
    + else
    + {
    ...
    + }
    
    Using different ordering for these if/else conditions makes the logic
    appear more complex. The second condition should be rearranged to be
    same order as the first: if (am_tablesync_worker()) ... else ...;
    
    ~~~
    
    launch_sync_worker:
    
    18.
    + (void) logicalrep_worker_launch((OidIsValid(relid)) ?
    WORKERTYPE_TABLESYNC : WORKERTYPE_SEQUENCESYNC,
    + MyLogicalRepWorker->dbid,
    + MySubscription->oid,
    + MySubscription->name,
    + MyLogicalRepWorker->userid,
    + relid, DSM_HANDLE_INVALID, false);
    
    I noticed you chose not to pass 'wtype' as a parameter here, but
    instead do the ternary to figure out the wtype.  AFAICT the caller
    already knows it, so why not just pass it in, instead of figuring it
    out again?
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  448. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-29T03:49:24Z

    Hi Vignesh,
    
    Some review comments patch V20251029-0001 (the test code only)
    
    ======
    src/test/subscription/t/036_sequences.pl
    
    1.
    +##########
    +## ALTER SUBSCRIPTION ... REFRESH PUBLICATION with (copy_data = off) should
    +# not update the sequence values for the new sequence.
    +##########
    +
    +# Create a new sequence 'regress_s4'
    +$node_publisher->safe_psql(
    + 'postgres', qq(
    + CREATE SEQUENCE regress_s4;
    + INSERT INTO regress_seq_test SELECT nextval('regress_s4') FROM
    generate_series(1,100);
    +));
    +
    
    AFAICT the sequence `regress_s3` (from the previous test part) was
    already a "new sequence" that had not yet been REFRESHED to the
    subscriber. So I think maybe there wasn't any need to create another
    sequence `regress_s4` for this test part.
    
    ~~~
    
    2.
    +# Check - newly published sequence values are not updated
    +$result = $node_subscriber->safe_psql(
    + 'postgres', qq(
    + SELECT last_value, log_cnt, is_called FROM regress_s4;
    +));
    
    Maybe that comment can give more details:
    # Check - newly published sequence values are not updated when (copy_data = off)
    
    ~~~
    
    3.
    +##########
    +# ALTER SUBSCRIPTION ... REFRESH PUBLICATION should report an error when:
    +# a) sequence definitions differ between the publisher and subscriber, or
    +# b) a sequence is missing on the publisher.
    +##########
    
    OK, you have these mismatch parameters and missing sequences test for
    "REFRESH PUBLICATION", but what about doing the same tests for
    "REFRESH SEQUENCES" -- e,g, I am thinking you can ALTER/DROP some
    publication that previously had synchronized OK, to verify what
    happens during "REFRESH SEQUENCES".
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  449. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-10-29T09:08:26Z

    Please find few trivial comments on 001:
    
    1)
    + * The sequencesync worker is responsible for synchronizing sequences marked in
    + * pg_subscription_rel.
    
    Shall we tweak it slightly to say:
    'A single sequencesync worker is responsible for synchronizing all
    sequences marked in pg_subscription_rel.'
    
    I feel the fact that there is 'single seq-sync worker' is important to
    mention in the file-header.
    
    2)
    sequencesync.c compiles without this:
    
    #include "replication/logicallauncher.h"
    
    3)
    Can we improve FetchRelationStates() slightly? Currently for sequence,
    it has an output parameter but for tables, it has return value, which
    looks odd to me.
    
    4)
    AllTablesyncsReady() has changed the name of the variable from
    has_subrels to has_tables which looks better. Do we need a similar
    change in  HasSubscriptionTablesCached as well?
    
    5)
    +is($result, '100|0|t', 'REFRESH PUBLICATION does not sync existing sequence');
    
    +is($result, '1|0|f',
    + 'REFRESH SEQUENCES will not sync newly published sequence');
    
    One has 'does not' while the other has 'will not'. Can we make both the same?
    
    thanks
    Shveta
    
    
    
    
  450. RE: Logical Replication of sequences

    Zhijie Hou (Fujitsu) <houzj.fnst@fujitsu.com> — 2025-10-29T10:31:13Z

    On Tuesday, October 28, 2025 8:30 PM vignesh C <vignesh21@gmail.com> wrote:
    > 
    > Peter's comments from [1] have also been addressed. The attached
    > v20251029 version patch has the changes for the same.
    
    Thanks for updating the patch. I have few comments on 0001:
    
    1.
    
    +	/*
    +	 * Record the remote sequence’s LSN in pg_subscription_rel and mark the
    
    There is a problem with the encoding of the single quote here.
    
    2.
    
    +#define isApplyWorker(worker) ((worker)->in_use && \
    +							   (worker)->type == WORKERTYPE_APPLY)
    
    The macro is unused.
    
    3.
    
    -FinishSyncWorker(void)
    +FinishSyncWorker()
    
    Is this change necessary ?
    
    
    4.
    
    +	LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
    +
    +	worker = logicalrep_worker_find(WORKERTYPE_APPLY,
    +									MyLogicalRepWorker->subid, InvalidOid,
    +									true);
    +	if (worker)
    +		worker->last_seqsync_start_time = 0;
    +
    +	LWLockRelease(LogicalRepWorkerLock);
    
    I think we should take Exclusive lock here because we are modifying
    the worker data.
    
    Best Regards,
    Hou zj
    
  451. Re: Logical Replication of sequences

    Dilip Kumar <dilipbalaut@gmail.com> — 2025-10-29T10:44:53Z

    On Tue, Oct 28, 2025 at 6:00 PM vignesh C <vignesh21@gmail.com> wrote:
    
    > On Mon, 27 Oct 2025 at 14:42, Chao Li <li.evan.chao@gmail.com> wrote:
    > >
    > >
    > > > On Oct 24, 2025, at 23:22, vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > Regards,
    > > > Vignesh
    > > >
    > <v20251024-0001-Rename-sync_error_count-to-tbl_sync_error_.patch><v20251024-0002-Add-worker-type-argument-to-logicalrep_wor.patch><v20251024-0003-New-worker-for-sequence-synchronization-du.patch><v20251024-0004-Documentation-for-sequence-synchronization.patch>
    > >
    > >
    > > The changes in 0001 are straightforward, looks good. I haven’t reviewed
    > 0004 yet. Got a few comments for 0002 and 0003.
    >
    > > 5 - 0003
    > > ```
    > > +/*
    > > + * Reset the last_seqsync_start_time of the sequencesync worker in the
    > > + * subscription's apply worker.
    > > + */
    > > +void
    > > +logicalrep_reset_seqsync_start_time(void)
    > > +{
    > > +       LogicalRepWorker *worker;
    > > +
    > > +       LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
    > > +
    > > +       /*
    > > +        * Set the last_seqsync_start_time for the sequence worker in
    > the apply
    > > +        * worker instead of the sequence sync worker, as the sequence
    > sync worker
    > > +        * has finished and is about to exit.
    > > +        */
    > > +       worker = logicalrep_worker_find(MyLogicalRepWorker->subid,
    > InvalidOid,
    > > +
    >  WORKERTYPE_APPLY, true);
    > > +       if (worker)
    > > +               worker->last_seqsync_start_time = 0;
    > > +
    > > +       LWLockRelease(LogicalRepWorkerLock);
    > > +}
    > > ```
    > >
    > > Two comments for this new function:
    > >
    > > * The function comment and in-code comment are redundant. Suggesting
    > move the in-code comment to function comment.
    > > * Why LW_SHARED is used? We are writing worker->last_seqsync_start_time,
    > shouldn’t LW_EXCLUSIVE be used?
    >
    > There will be only one sequence sync worker and only this process is
    > going to update this, so LW_SHARED is enough to find the apply worker.
    >
    > > 6 - 0003
    > > ```
    > > +       /*
    > > +        * Count running sync workers for this subscription, while we
    > have the
    > > +        * lock.
    > > +        */
    > > +       nsyncworkers =
    > logicalrep_sync_worker_count(MyLogicalRepWorker->subid);
    > > +       LWLockRelease(LogicalRepWorkerLock);
    > > +
    > > +       launch_sync_worker(nsyncworkers, InvalidOid,
    > > +
    > &MyLogicalRepWorker->last_seqsync_start_time);
    > > ```
    > >
    > > I think here could be a race condition. Because the lock is acquired in
    > LW_SHARED, meaning multiple caller may get the same nsyncworkers. Then it
    > launches sync worker based on nsyncworkers, which would use inaccurate
    > nsyncworkers, because between LWLockRelease() and launch_sync_worker(),
    > another worker might be started.
    > >
    > > But if that is not the case, only one caller should call
    > ProcessSyncingSequencesForApply(), then why the lock is needed?
    >
    > Sequence sync worker will be started only by the apply worker, another
    > worker cannot be started for this subscription between LWLockRelease()
    > and launch_sync_worker() as this apply worker is responsible for it
    > and the apply worker is active with current work. Same logic is used
    > for table sync workers too.
    >
    > > 7 - 0003
    > > ```
    > > +       if (insuffperm_seqs->len)
    > > +       {
    > > +               appendStringInfo(combined_error_detail, "Insufficient
    > permission for sequence(s): (%s)",
    > > +                                                insuffperm_seqs->data);
    > > +               appendStringInfoString(combined_error_hint, "Grant
    > permissions for the sequence(s).");
    > > +       }
    > > ```
    > >
    > > “Grant permissions” is unclear. Should it be “Grant UPDATE privilege”?
    >
    > Modified
    >
    > > 8 - 0003
    > > ```
    > > +                       appendStringInfoString(combined_error_hint, "
    > For mismatched sequences, alter or re-create local sequences to have
    > matching parameters as publishers.");
    > > ```
    > >
    > > “To have matching parameters as publishers” grammatically sound not
    > good. Maybe revision to “to match the publisher’s parameters”.
    >
    > Modified
    >
    > > 9 - 0003
    > > ```
    > > +               /*
    > > +                * current_indexes is not incremented sequentially
    > because some
    > > +                * sequences may be missing, and the number of fetched
    > rows may not
    > > +                * match the batch size. The `hash_search` with
    > HASH_REMOVE takes care
    > > +                * of the count.
    > > +                */
    > > ```
    > >
    > > Typo: current_indexes => current_index
    >
    > Modified
    >
    > > 10 - 0003
    > > ```
    > > -       /* Find the leader apply worker and signal it. */
    > > -       logicalrep_worker_wakeup(MyLogicalRepWorker->subid, InvalidOid);
    > > +       /*
    > > +        * This is a clean exit of the sequencesync worker; reset the
    > > +        * last_seqsync_start_time.
    > > +        */
    > > +       if (wtype == WORKERTYPE_SEQUENCESYNC)
    > > +               logicalrep_reset_seqsync_start_time();
    > > +       else
    > > +               /* Find the leader apply worker and signal it. */
    > > +               logicalrep_worker_wakeup(MyLogicalRepWorker->subid,
    > InvalidOid);
    > > ```
    > >
    > > The comment “this is a clean exist of sequencsync worker” is specific to
    > “if”, so suggesting moving into “if”. And “this is a clean exis of the
    > sequencesyc worker” is not needed, keep consistent with the comment in
    > “else”.
    >
    > Modified
    >
    > > 11 - 0003
    > > ```
    > > +void
    > > +launch_sync_worker(int nsyncworkers, Oid relid, TimestampTz
    > *last_start_time)
    > > +{
    > > +       /* If there is a free sync worker slot, start a new sync worker
    > */
    > > +       if (nsyncworkers < max_sync_workers_per_subscription)
    > > +       {
    > > ```
    > >
    > > The entire function is under an “if”, so we can do “if (!…) return”, so
    > saves a level of indent.
    >
    > Modified
    >
    > Peter's comments from [1] have also been addressed. The attached
    > v20251029 version patch has the changes for the same.
    >
    > [1] -
    > https://www.postgresql.org/message-id/CAHut%2BPtMc1fr6cQvUAnxRE%2Bbuim5m-d9M2dM0YAeEHNkS9KzBw%40mail.gmail.com
    
    
    
    Are you planning to merge 0001 and 0002, I don't think first we want to
    commit the solution with a hash and then commit with the list. So for
    review also we better merge these 2 so that we don't need to review the
    changes with hash as we are not going to commit that change if we agree
    that we want to go ahead with the list.
    
    -- 
    Regards,
    Dilip Kumar
    Google
    
  452. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-29T16:10:24Z

    On Wed, 29 Oct 2025 at 08:17, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Some more review comments for v20251029-0001.
    >
    > ======
    > .../replication/logical/sequencesync.c
    >
    > 1.
    > + * The apply worker periodically scans pg_subscription_rel for sequences in
    > + * INIT state. When such sequences are found, it spawns a
    > + * sequencesync worker to handle synchronization.
    >
    > I did not see anything in this header comment that says there is
    > currently no more than 1 sequencesync worker. The above part of the
    > comment doesn't make that clear.
    
    Modified
    
    > ~~~
    >
    > 2.
    > + * Handle sequence synchronization cooperation from the apply worker.
    >
    > Is it simpler just to say:
    > Apply worker determines if sequence synchronization is needed.
    
    Modified
    
    > ~~~
    >
    > report_error_sequences:
    >
    > 3.
    > +static void
    > +report_error_sequences(StringInfo insuffperm_seqs, StringInfo mismatched_seqs,
    > +    StringInfo missing_seqs)
    >
    > Function name seems strange. How about 'ereport_sequence_errors'?
    
    I preferred report_sequence_errors over ereport_sequence_errors.
    
    > ~~~
    >
    > 4.
    > + if (mismatched_seqs->len)
    > + {
    > + if (insuffperm_seqs->len)
    > + {
    > + appendStringInfo(combined_error_detail, "; mismatched sequence(s) on
    > subscriber: (%s)",
    > + mismatched_seqs->data);
    > + appendStringInfoString(combined_error_hint, " For mismatched
    > sequences, alter or re-create local sequences to match the publisher's
    > parameters.");
    > + }
    > + else
    > + {
    > + appendStringInfo(combined_error_detail, "Mismatched sequence(s) on
    > subscriber: (%s)",
    > + mismatched_seqs->data);
    > + appendStringInfoString(combined_error_hint, "For mismatched
    > sequences, alter or re-create local sequences to match the publisher's
    > parameters.");
    > + }
    > + }
    > +
    > + if (missing_seqs->len)
    > + {
    > + if (insuffperm_seqs->len || mismatched_seqs->len)
    > + {
    > + appendStringInfo(combined_error_detail, "; missing sequence(s) on
    > publisher: (%s)",
    > + missing_seqs->data);
    > + appendStringInfoString(combined_error_hint, " For missing sequences,
    > remove them locally or run ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > to refresh the subscription.");
    > + }
    > + else
    > + {
    > + appendStringInfo(combined_error_detail, "Missing sequence(s) on
    > publisher: (%s)",
    > + missing_seqs->data);
    > + appendStringInfoString(combined_error_hint, "For missing sequences,
    > remove them locally or run ALTER SUBSCRIPTION ... REFRESH PUBLICATION
    > to refresh the subscription.");
    > + }
    > + }
    >
    >
    > This logic has a lot of duplication just to handle the separate
    > multiple details/hints. I think it can be simplified a lot.
    >
    > SUGGESTION
    > if (mismatched_seqs->len)
    > {
    >   if (combined_error_detail->len)
    >   {
    >     appendStringInfo(combined_error_detail, "; ");
    >     appendStringInfoChar(combined_error_hint, ' ');
    >   }
    >   appendStringInfo(combined_error_detail, "Mismatched sequence(s) ...);
    >   appendStringInfoString(combined_error_hint, "For mismatched sequences, ...);
    > }
    > if (missing_seqs->len)
    > {
    >   if (combined_error_detail->len)
    >   {
    >     appendStringInfo(combined_error_detail, "; ");
    >     appendStringInfoChar(combined_error_hint, ' ');
    >   }
    >   appendStringInfo(combined_error_detail, "Missing sequence(s) on ...);
    >   appendStringInfoString(combined_error_hint, "For missing sequences,
    > remove ...);
    > }
    
    Modified
    
    > ~~~
    >
    > get_remote_sequence_info:
    >
    > 5.
    > +static void
    > +get_remote_sequence_info(TupleTableSlot *slot, LogicalRepSeqHashKey *key,
    > + int64 *last_value, bool *is_called,
    > + XLogRecPtr *page_lsn, Oid *remote_typid,
    > + int64 *remote_start, int64 *remote_increment,
    > + int64 *remote_min, int64 *remote_max,
    > + bool *remote_cycle)
    >
    > I felt this code might be better if you would introduce a new
    > structure (or add to an existing one?) to hold all the members instead
    > of declaring a dozen variables and passing them as parameters. So, a
    > cleaner function signature here might be like:
    >
    > static SequenceInfo get_remote_sequence_info(TupleTableSlot *slot).
    >
    > This may also allow you to simplify other code that passes so many
    > members as parameters -- e.g. also the validation function.
    
    I will take this in the next version or little later.
    
    > ~~~
    > validate_sequence:
    >
    > 6.
    > + /* Sequence was concurrently dropped */
    > + if (!sequence_rel)
    > + return COPYSEQ_SKIPPED;
    > +
    > + /* Sequence was concurrently dropped */
    > + tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    > + if (!HeapTupleIsValid(tup))
    > + return COPYSEQ_SKIPPED;
    > +
    > + /* Sequence was concurrently invalidated */
    > + if (!seqinfo->entry_valid)
    > + {
    > + ReleaseSysCache(tup);
    > + return COPYSEQ_SKIPPED;
    > + }
    >
    > 6a.
    > All those comments might be better written as questions. e.g.
    > /* Sequence was concurrently dropped? */
    > /* Sequence was concurrently dropped? */
    > /* Sequence was concurrently invalidated? */
    
    Modified
    
    > ~
    >
    > 6b.
    > + /* Sequence was concurrently dropped */
    > + tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    > + if (!HeapTupleIsValid(tup))
    > + return COPYSEQ_SKIPPED;
    >
    > I think the 2nd comment belongs after the tup assignment.
    
    Modified
    
    > ~
    >
    > 6c.
    > + local_seq = (Form_pg_sequence) GETSTRUCT(tup);
    > + if (local_seq->seqtypid != remote_typid ||
    > + local_seq->seqstart != remote_start ||
    > + local_seq->seqincrement != remote_increment ||
    > + local_seq->seqmin != remote_min ||
    > + local_seq->seqmax != remote_max ||
    > + local_seq->seqcycle != remote_cycle)
    > + result = COPYSEQ_MISMATCH;
    >
    > This should have a comment like the others. e.g.
    > /* Sequence parameters for remote/local are the same? */
    
    Modified
    
    > ~~~
    >
    > copy_sequence:
    >
    > 7.
    > +/*
    > + * Apply remote sequence state to local sequence and mark it as synchronized.
    > + */
    >
    > Is it better to explicitly name the state here too? e.g.
    >
    > /and mark it as synchronized/and mark it as synchronized (READY)/
    
    Modified
    
    > ~~~
    >
    > 8.
    > + /*
    > + * Make sure that the sequence is copied as table owner, unless the user
    > + * has opted out of that behaviour.
    > + */
    > + if (!MySubscription->runasowner)
    > + SwitchToUntrustedUser(seqinfo->seqowner, &ucxt);
    >
    > 8a.
    > Is "table owner" the correct term here?
    
    Changed it to sequence owner
    
    > ~
    >
    > 8b.
    > Why not use the 'run_as_owner' variable?
    
    modified
    
    > ~~~
    >
    > copy_sequences:
    >
    > 9.
    > + ereport(ERROR,
    > + errcode(ERRCODE_CONNECTION_FAILURE),
    > + errmsg("could not receive list of sequence information from the
    > publisher: %s",
    > +    res->err));
    >
    > How about just:
    > "could not fetch sequence information from the publisher: %s",
    
    modified
    
    > ~~~
    >
    > 10.
    > + CopySeqResult result;
    >
    > 'result' seems a slightly meaningless variable name since this is not
    > even returned from the function.
    
    Changed it
    
    > ~~~
    >
    > sequencesync_list_invalidate_cb:
    >
    > 11.
    > + if (reloid != InvalidOid)
    >
    > Use macro !OidIsValid(reloid)
    
    Modified
    
    > ~
    >
    > 12.
    > + hash_seq_init(&status, sequences_to_copy);
    > +
    >
    > This init is common for the if/else so could be done outside.
    
    This code is removed now
    
    > ~~~
    >
    > LogicalRepSeqMatchFunc:
    >
    > 13.
    > + /* Compare by namespace name first */
    > + cmp = strcmp(k1->nspname, k2->nspname);
    > + if (cmp != 0)
    > + return cmp;
    > +
    > + /* If namespace names are equal, compare by sequence name */
    > + return strcmp(k1->seqname, k2->seqname);
    >
    > A simpler way to write this comparator might look like:
    >
    > /* Compare by namespace name first, then by sequence name */
    > cmp = strcmp(k1->nspname, k2->nspname);
    > if (cmp == 0)
    >   cmp = strcmp(k1->seqname, k2->seqname);
    >
    > return cmp;
    
    This code is removed now
    
    > ~~~
    >
    > LogicalRepSyncSequences:
    >
    > 14.
    > +/*
    > + * Start syncing the sequences in the sequencesync worker.
    > + */
    > +static void
    > +LogicalRepSyncSequences(void)
    >
    > Might need a different function comment. This one seems almost the
    > same as the function comment for copy_sequences().
    
    Modified
    
    > ~~~
    >
    > 15.
    > + key.seqname = RelationGetRelationName(sequence_rel);
    > + key.nspname = get_namespace_name(RelationGetNamespace(sequence_rel));
    > +
    > + /* Allocate the tracking info in a permanent memory context. */
    > + oldctx = MemoryContextSwitchTo(CacheMemoryContext);
    > +
    > + seq_entry = hash_search(sequences_to_copy, &key, HASH_ENTER, &found);
    > + Assert(!found);
    > +
    > + memset(seq_entry, 0, sizeof(LogicalRepSequenceInfo));
    > +
    > + seq_entry->localrelid = subrel->srrelid;
    > + seq_entry->remote_seq_queried = false;
    > + seq_entry->seqowner = sequence_rel->rd_rel->relowner;
    > + seq_entry->entry_valid = true;
    >
    > Nit. It seems more natural to put the nspname before the seqname.
    >
    > So,
    > key.nspname = ...
    > key.seqname = ...
    >
    > and
    > seq_entry->nspname = pstrdup(key.nspname);
    > seq_entry->seqname = pstrdup(key.seqname);
    
    This code has been removed, there was one more place where the
    ordering was different, modified it there.
    
    > ~~~
    >
    > LogicalRepSyncSequences:
    >
    > 16.
    > + /* If there are any sequences that need to be copied */
    > + if (hash_get_num_entries(sequences_to_copy))
    > + copy_sequences(LogRepWorkerWalRcvConn, subid);
    >
    > If there are no sequences to copy then AFAICT (from
    > SequenceSyncWorkerMain) this sequencesync worker is just going to just
    > stop and exit isn't it? So, why didn't we check this earlier and
    > perhaps could have avoided making a publisher connection
    > LogRepWorkerWalRcvConn for no reason?
    
    Modified
    
     ======
    > src/backend/replication/logical/syncutils.c
    >
    > FinishSyncWorker:
    >
    > 17.
    > + if (am_tablesync_worker())
    > + ereport(LOG,...));
    > + else
    > + ereport(LOG,...);
    >
    > + if (am_sequencesync_worker())
    > + {
    > ...
    > + }
    > + else
    > + {
    > ...
    > + }
    >
    > Using different ordering for these if/else conditions makes the logic
    > appear more complex. The second condition should be rearranged to be
    > same order as the first: if (am_tablesync_worker()) ... else ...;
    
    Modified
    
    > ~~~
    >
    > launch_sync_worker:
    >
    > 18.
    > + (void) logicalrep_worker_launch((OidIsValid(relid)) ?
    > WORKERTYPE_TABLESYNC : WORKERTYPE_SEQUENCESYNC,
    > + MyLogicalRepWorker->dbid,
    > + MySubscription->oid,
    > + MySubscription->name,
    > + MyLogicalRepWorker->userid,
    > + relid, DSM_HANDLE_INVALID, false);
    >
    > I noticed you chose not to pass 'wtype' as a parameter here, but
    > instead do the ternary to figure out the wtype.  AFAICT the caller
    > already knows it, so why not just pass it in, instead of figuring it
    > out again?
    
    Modified
    
    Shveta's comments from [1] have also been addressed in this version.
    Dilip's merge suggestion from [2] has also been addressed in this version.
    
    The attached v20251029_2 version patch has the fixes for the same.
    
    [1] - https://www.postgresql.org/message-id/CAJpy0uCkt4V95un1025xV%2BBoLOXg0DTk418Di_f6gerpuezBmA%40mail.gmail.com
    [2] - https://www.postgresql.org/message-id/CAFiTN-v1mm%3DwAMBVT82Ok9YrGG7o-wszxw4RHsmKk1oP%2B%3DrJnA%40mail.gmail.com
    
    Regards,
    Vignesh
    
  453. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-29T16:13:18Z

    On Wed, 29 Oct 2025 at 09:19, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Some review comments patch V20251029-0001 (the test code only)
    >
    > ======
    > src/test/subscription/t/036_sequences.pl
    >
    > 1.
    > +##########
    > +## ALTER SUBSCRIPTION ... REFRESH PUBLICATION with (copy_data = off) should
    > +# not update the sequence values for the new sequence.
    > +##########
    > +
    > +# Create a new sequence 'regress_s4'
    > +$node_publisher->safe_psql(
    > + 'postgres', qq(
    > + CREATE SEQUENCE regress_s4;
    > + INSERT INTO regress_seq_test SELECT nextval('regress_s4') FROM
    > generate_series(1,100);
    > +));
    > +
    >
    > AFAICT the sequence `regress_s3` (from the previous test part) was
    > already a "new sequence" that had not yet been REFRESHED to the
    > subscriber. So I think maybe there wasn't any need to create another
    > sequence `regress_s4` for this test part.
    
    Modified
    
    > ~~~
    >
    > 2.
    > +# Check - newly published sequence values are not updated
    > +$result = $node_subscriber->safe_psql(
    > + 'postgres', qq(
    > + SELECT last_value, log_cnt, is_called FROM regress_s4;
    > +));
    >
    > Maybe that comment can give more details:
    > # Check - newly published sequence values are not updated when (copy_data = off)
    
    Modified
    
    > ~~~
    >
    > 3.
    > +##########
    > +# ALTER SUBSCRIPTION ... REFRESH PUBLICATION should report an error when:
    > +# a) sequence definitions differ between the publisher and subscriber, or
    > +# b) a sequence is missing on the publisher.
    > +##########
    >
    > OK, you have these mismatch parameters and missing sequences test for
    > "REFRESH PUBLICATION", but what about doing the same tests for
    > "REFRESH SEQUENCES" -- e,g, I am thinking you can ALTER/DROP some
    > publication that previously had synchronized OK, to verify what
    > happens during "REFRESH SEQUENCES".
    
    I'm planning to do this in a later version.
    
    The changes for the same are available in the v20251029_2 version
    patch attached at [1].
    [1] - https://www.postgresql.org/message-id/CALDaNm18siwD6Mamv8Dd8ubwSCw3Fi6SnB4B3Lr%2B4R7snLkfeA%40mail.gmail.com
    
    Regards,
    Vignesh
    
    
    
    
  454. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-30T02:42:27Z

    Hi Vignesh,
    
    Some review comments for v20251029_2-0001
    
    ======
    General.
    
    1.
    I think it's more readable to consistently write the state name in
    uppercase. There are a few affected comments:
    
    e.g.
    + * we identify non-ready tables and non-ready sequences together to ensure
    becomes
    + * we identify non-READY tables and non-READY sequences together to ensure
    
    e.g.
    + * has_pending_subtables: true if the subscription has one or more tables that
    + * are not in ready state, otherwise false.
    + * has_pending_subsequences: true if the subscription has one or more sequences
    + * that are not in ready state, otherwise false.
    becomes
    + * has_pending_subtables: true if the subscription has one or more tables that
    + * are not in READY state, otherwise false.
    + * has_pending_subsequences: true if the subscription has one or more sequences
    + * that are not in READY state, otherwise false.
    
    e.g.
    + /* Fetch tables and sequences that are in non-ready state. */
    becomes
    + /* Fetch tables and sequences that are in non-READY state. */
    
    ======
    .../replication/logical/sequencesync.c
    
    2.
    + * A single sequencesync worker is responsible for synchronizing all sequences
    + * marked in pg_subscription_rel. It begins by retrieving the list of sequences
    
    typo? /marked in pg_subscription_rel/mapped in pg_subscription_rel/
    
    ~~~
    
    3.
    +static void
    +report_sequence_errors(StringInfo insuffperm_seqs, StringInfo mismatched_seqs,
    +    StringInfo insuffperm_seqs)
    
    Perhaps this function should also have an assertion:
    
    Assert(insuffperm_seqs->len || mismatched_seqs->len || insuffperm_seqs->len);
    
    ~~~
    
    copy_sequences:
    
    4.
    + int current_index = 0;
    
    It's not really a current index. Maybe a better name for this variable
    is something more like 'cur_batch_base_index'?
    
    ~~~
    
    LogicalRepSyncSequences:
    
    5.
    + if (!seqinfos)
    + return;
    +
    
    Maybe this needs some comment to say it is an early exit, for when
    somehow the sequencesync worker started to do some work, but then it
    found that there was nothing to do. Maybe also describe how this could
    happen?
    
    ======
    src/backend/replication/logical/syncutils.c
    
    launch_sync_worker
    
    6.
    + * wtype: sync worker type.
    + * nsyncworkers: Number of currently running sync workers for the subscription.
    + * relid:  InvalidOid for sequencesync worker, actual relid for tablesync
    + * worker.
    + * last_start_time: Pointer to the last start time of the worker.
    + */
    +void
    +launch_sync_worker(LogicalRepWorkerType wtype, int nsyncworkers, Oid relid,
    +    TimestampTz *last_start_time)
    
    
    Now it might be nice to have a sanity assert to match that function
    comment. e.g.
    
    Assert((wtype == WORKERTYPE_TABLESYNC) == OidIsValid(relid));
    
    ~~~
    
    FetchRelationStates:
    
    7.
      foreach(lc, rstates)
      {
    - rstate = palloc(sizeof(SubscriptionRelState));
    - memcpy(rstate, lfirst(lc), sizeof(SubscriptionRelState));
    - table_states_not_ready = lappend(table_states_not_ready, rstate);
    + SubscriptionRelState *subrel = (SubscriptionRelState *) lfirst(lc);
    
    Should we change that to:
    foreach_ptr(SubscriptionRelState, subrel, rstates)
    
    ======
    src/backend/replication/logical/tablesync.c
    
    ProcessSyncingTablesForApply:
    
    8.
    bool started_tx = false;
    bool should_exit = false;
    Relation rel = NULL;
    
    Assert(!IsTransactionState());
    
    /* We need up-to-date sync state info for subscription tables here. */
    FetchRelationStates(NULL, NULL, &started_tx);
    
    ~
    
    It's not necessary here to assign that `started_tx` to false at the
    declaration, because FetchRelationStates will set it.
    ProcessSyncingSequencesForApply() does not assign a declaration like
    this, so I felt here should not do it either.
    
    Alternatively, leave this code as-is, change
    ProcessSyncingSequencesForApply() to assign it false too. And then
    Assert(*started_tx == false) inside the FetchRelationStates function.
    
    Whatever way you choose, the point is that all caller code should be consistent.
    
    ~~~
    
    AllTablesyncsReady:
    
    9.
    Ditto previous comment about the inconsistent auto-assignment of started_tx.
    
    ~~~
    
    HasSubscriptionTablesCached:
    
    10.
    Ditto previous comment about the inconsistent auto-assignment of started_tx.
    
    ======
    src/test/subscription/t/036_sequences.pl
    
    11.
    The comments can be more helpful if they also name the sequences
    involved -- It saves having to go hunting to see what is new and what
    is existing. I mean only small changes like below:
    
    BEFORE
    # Check - existing sequence is not synced
    # Check - newly published sequence is synced
    
    SUGGESTION
    # Check - existing sequence ('regress_s1') is not synced
    # Check - newly published sequence ('regress_s2') is synced
    
    etc in multiple places.
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  455. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-30T10:49:46Z

    On Thu, Oct 30, 2025 at 8:12 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > 3.
    > +static void
    > +report_sequence_errors(StringInfo insuffperm_seqs, StringInfo mismatched_seqs,
    > +    StringInfo insuffperm_seqs)
    >
    > Perhaps this function should also have an assertion:
    >
    > Assert(insuffperm_seqs->len || mismatched_seqs->len || insuffperm_seqs->len);
    >
    
    I don't think such an assertion is helpful. As of now, this is called
    from only one place where we ensure that one of the conditions
    mentioned in assert is true but in future even if we call that without
    any condition being true, it will just be a harmless call.
    
    Other review comments:
    ===================
    1. In copy_sequences, we start a transaction before getting the
    changes from the publisher and keep using it till we copy all
    sequences. If we don't need to retain lock while querying from a
    publisher, then can't we even commit the xact before that and start a
    new one for the copy_sequence part? Is it possible that we fetch the
    required sequence information in LogicalRepSyncSequences()?
    
    2. Isn't it better to add some comments as to why we didn't decide to
    retain locks on required sequences while querying the publisher, and
    rather re-validate them later?
    
    3. To avoid a lot of parameters in get_remote_sequence_info and
    validate_sequence(), can we have one function call say
    get_and_validate_seq_info()? It will retrieve only the parameters
    required by copy_sequence.
    
    4.
    validate_sequence()
    {
    ...
    + /* Sequence was concurrently invalidated? */
    + if (!seqinfo->entry_valid)
    + {
    + ReleaseSysCache(tup);
    + return COPYSEQ_SKIPPED;
    + }
    
    So, if the sequence is renamed concurrently, we get the cause as
    SKIPPED but shouldn't it be COPYSEQ_MISMATCH? Is it possible to
    compare the local sequence name with the remote name in
    validate_sequence() after taking lock on sequence relation? If so, we
    can return the state as COPYSEQ_MISMATCH.
    
    Apart from the above, I have modified comments at various places in
    the patch, see attached.
    
    -- 
    With Regards,
    Amit Kapila.
    
  456. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-10-30T16:30:15Z

    On Thu, 30 Oct 2025 at 16:20, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Oct 30, 2025 at 8:12 AM Peter Smith <smithpb2250@gmail.com> wrote:
    > >
    > > 3.
    > > +static void
    > > +report_sequence_errors(StringInfo insuffperm_seqs, StringInfo mismatched_seqs,
    > > +    StringInfo insuffperm_seqs)
    > >
    > > Perhaps this function should also have an assertion:
    > >
    > > Assert(insuffperm_seqs->len || mismatched_seqs->len || insuffperm_seqs->len);
    > >
    >
    > I don't think such an assertion is helpful. As of now, this is called
    > from only one place where we ensure that one of the conditions
    > mentioned in assert is true but in future even if we call that without
    > any condition being true, it will just be a harmless call.
    >
    > Other review comments:
    > ===================
    > 1. In copy_sequences, we start a transaction before getting the
    > changes from the publisher and keep using it till we copy all
    > sequences. If we don't need to retain lock while querying from a
    > publisher, then can't we even commit the xact before that and start a
    > new one for the copy_sequence part? Is it possible that we fetch the
    > required sequence information in LogicalRepSyncSequences()?
    
    Change it to fetching it in LogicalRepSyncSequences
    
    > 2. Isn't it better to add some comments as to why we didn't decide to
    > retain locks on required sequences while querying the publisher, and
    > rather re-validate them later?
    
    Added comments for the same
    
    > 3. To avoid a lot of parameters in get_remote_sequence_info and
    > validate_sequence(), can we have one function call say
    > get_and_validate_seq_info()? It will retrieve only the parameters
    > required by copy_sequence.
    
    Modified
    
    > 4.
    > validate_sequence()
    > {
    > ...
    > + /* Sequence was concurrently invalidated? */
    > + if (!seqinfo->entry_valid)
    > + {
    > + ReleaseSysCache(tup);
    > + return COPYSEQ_SKIPPED;
    > + }
    >
    > So, if the sequence is renamed concurrently, we get the cause as
    > SKIPPED but shouldn't it be COPYSEQ_MISMATCH? Is it possible to
    > compare the local sequence name with the remote name in
    > validate_sequence() after taking lock on sequence relation? If so, we
    > can return the state as COPYSEQ_MISMATCH.
    
    Modified
    
    > Apart from the above, I have modified comments at various places in
    > the patch, see attached.
    
    Thanks, I have merged them.
    
    The attached v20251030 version patch has the changes for the same.
    I have also addressed Peter's comments from [1] and Hou-san's comments from [2].
    
    [1] - https://www.postgresql.org/message-id/CAHut%2BPt73A8XNnBSiF5wEfqM4mT6ofVwW9BXw3oUjbGsaYQN_g%40mail.gmail.com
    [2] - https://www.postgresql.org/message-id/TY4PR01MB16907CAA300EE41232FB0BA8194FAA%40TY4PR01MB16907.jpnprd01.prod.outlook.com
    
    Regards,
    Vignesh
    
  457. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-31T02:04:16Z

    Hi Vignesh,
    
    Some review comments for v20251030-0001
    
    ======
    Commit message
    
    1.
    3) ALTER SUBSCRIPTION ... REFRESH SEQUENCES
        - (A new command introduced in PG19 by a prior patch.)
        - All sequences in pg_subscription_rel are reset to DATASYNC state.
    ~
    
    DATASYNC? Just above, it says the only possible states for sequences
    are INIT and READY.
    
    ======
    .../replication/logical/sequencesync.c
    
    2.
    + * A single sequencesync worker is responsible for synchronizing all sequences
    + * in INIT state in pg_subscription_rel. It begins by retrieving the list of
    + * sequences flagged for synchronization. These sequences are then processed
    + * in batches, allowing multiple entries to be synchronized within a single
    + * transaction. The worker fetches the current sequence values and page LSNs
    + * from the remote publisher, updates the corresponding sequences on the local
    + * subscriber, and finally marks each sequence as READY upon successful
    + * synchronization.
    + *
    
    Those first 2 sentences seem repetitive because AFAIK "in INIT state"
    and "flagged for synchronization" are exactly the same thing.
    
    SUGGESTION
    A single sequencesync worker is responsible for synchronizing all
    sequences. It begins by retrieving the list of sequences that are
    flagged for needing synchronization (e.g. those with INIT state).
    
    ~~~
    
    get_and_validate_seq_info:
    
    3.
    +/*
    + * get_and_validate_seq_info
    + *
    + * Extracts remote sequence information from the tuple slot received from the
    + * publisher and validates it against the corresponding local sequence
    + * definition.
    + */
    
    Missing comma.
    
    /publisher and validates/publisher, and validates/
    
    ~~~
    
    4.
    Now that this function is in 2 parts, I think each part should be
    clearly identified with comments, something like:
    
    PART 1:
    /*
     * 1. Extract sequence information from the tuple slot received from the
     * publisher
     */
    
    PART 2:
    /*
     * 2. Compare the remote sequence definition to the local sequence definition,
     * and report any discrepancies.
     */
    
    ~~~
    
    5.
    + seqinfo_local = (LogicalRepSequenceInfo *) list_nth(seqinfos, seqidx);
    + seqinfo_local->found_on_pub = true;
    + *seqinfo = seqinfo_local;
    
    Is this separate `seqinfo_local` variable needed? It seems always
    unconditionally assigned to the parameter, so you might as well just
    do without the extra variable. Maybe just rename the parameter as
    `seqinfo_local`?
    
    ~~~
    
    6.
    + if (!*sequence_rel) /* Sequence was concurrently dropped? */
    + return COPYSEQ_SKIPPED;
    +
    + tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo_local->localrelid));
    + if (!HeapTupleIsValid(tup)) /* Sequence was concurrently dropped? */
    + return COPYSEQ_SKIPPED;
    
    Nit. IMO the code was easier to read in the previous patch version,
    when it was commented above the code like:
    
    /* Sequence was concurrently dropped */
    if (!*sequence_rel)
      return COPYSEQ_SKIPPED;
    
    /* Sequence was concurrently dropped */
    tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    if (!HeapTupleIsValid(tup))
      return COPYSEQ_SKIPPED;
    ~~~
    
    copy_sequence:
    
    7.
    +static CopySeqResult
    +copy_sequence(LogicalRepSequenceInfo *seqinfo, int64 last_value,
    +   bool is_called, XLogRecPtr page_lsn, Oid seqowner)
    +{
    + UserContext ucxt;
    + AclResult aclresult;
    + bool run_as_owner = MySubscription->runasowner;
    + Oid seqoid = seqinfo->localrelid;
    +
    + /*
    + * Make sure that the sequence is copied as sequence owner, unless the
    + * user has opted out of that behaviour.
    + */
    + if (!run_as_owner)
    + SwitchToUntrustedUser(seqowner, &ucxt);
    
    The code/comment seems contradictory because IMO it is vague what
    runasowner member means -- which owner? AFAIK `run_as_owner` really
    means "run as *subscription* owner". Ideally, the
    MySubscription->runasowner member might be renamed to 'runassubowner'
    but maybe that is a bigger change than you want to make for this
    patch.
    
    So, maybe just the comment can be rewritten for more clarity.
    
    SUGGESTION:
    If the user did not opt to run as the owner of the subscription
    ('run_as_owner'), then copy the sequence as the owner of the sequence.
    
    (Also, make the similar comment change for the equivalent place in tablesync.c).
    
    ~~~
    
    copy_sequences:
    
    8.
    + ereport(LOG,
    + errmsg("logical replication sequence synchronization for
    subscription \"%s\" - total unsynchronized: %d",
    +    MySubscription->name, list_length(seqinfos)));
    +
    + while (cur_batch_base_index < list_length(seqinfos))
    
    Would it be tidier to declare int n_seqinfos = list_length(seqinfos);
    instead of using list_length() multiple times in this function.
    
    ~~~
    
    9.
    + * We deliberately avoid acquiring a local lock on the sequence before
    + * querying the publisher to prevent potential distributed deadlocks
    + * in bi-directional replication setups. For instance, a concurrent
    + * ALTER SEQUENCE on one node might block this worker, while the
    + * worker's own local lock simultaneously blocks a similar operation
    + * on the other nod resulting in a circular wait that spans both nodes
    + * and remains undetected.
    
    typo: /nod/node/
    
    ~~~
    
    10.
    + int64 last_value;
    + bool is_called;
    + XLogRecPtr page_lsn;
    + CopySeqResult sync_status;
    + LogicalRepSequenceInfo *seqinfo;
    +
    + CHECK_FOR_INTERRUPTS();
    +
    + if (ConfigReloadPending)
    + {
    + ConfigReloadPending = false;
    + ProcessConfigFile(PGC_SIGHUP);
    + }
    +
    + sync_status = get_and_validate_seq_info(slot, &sequence_rel,
    + &seqinfo, &page_lsn,
    + &last_value, &is_called);
    + if (sync_status == COPYSEQ_SUCCESS)
    + sync_status = copy_sequence(seqinfo, last_value, is_called,
    + page_lsn,
    + sequence_rel->rd_rel->relowner);
    
    Why does LogicalRepSequenceInfo only have to be metadata? Can't those
    `page_lsn`, `last_value`, and `is_called` also be made members of
    LogicalRepSequenceInfo, so you don't have to declare them and pass
    them all in and out as parameters here?
    
    ======
    src/test/subscription/t/036_sequences.pl
    
    11.
    +$node_publisher->safe_psql(
    + 'postgres', qq(
    + DROP SEQUENCE regress_s4;
    +));
    +
    +# Verify that an error is logged for the missing sequence ('regress_s4').
    +$node_subscriber->wait_for_log(
    + qr/ERROR: ( [A-Z0-9]+:)? logical replication sequence
    synchronization failed for subscription "regress_seq_sub"\n.*DETAIL:.*
    Missing sequence\(s\) on publisher: \("public.regress_s4"\)/,
    + $log_offset);
    
    I felt that psql DROP code belongs below the comment too.
    Alternatively, add another comment for that DROP, like:
    # Drop the sequence ('regress_s4') in preparation for the next test
    
    ~~~
    
    12.
    There is still a yet-to-be-implemented test combination as previously
    reported [1, comment #3], right?
    
    ======
    [1] https://www.postgresql.org/message-id/CAHut%2BPu%2BwTfWwCUUUL%2BcqsHFZ-ptY6CWe8FYM3by901NvLArCQ%40mail.gmail.com
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  458. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-10-31T04:40:52Z

    On Fri, Oct 31, 2025 at 7:34 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > ======
    > .../replication/logical/sequencesync.c
    >
    > 2.
    > + * A single sequencesync worker is responsible for synchronizing all sequences
    > + * in INIT state in pg_subscription_rel. It begins by retrieving the list of
    > + * sequences flagged for synchronization. These sequences are then processed
    > + * in batches, allowing multiple entries to be synchronized within a single
    > + * transaction. The worker fetches the current sequence values and page LSNs
    > + * from the remote publisher, updates the corresponding sequences on the local
    > + * subscriber, and finally marks each sequence as READY upon successful
    > + * synchronization.
    > + *
    >
    > Those first 2 sentences seem repetitive because AFAIK "in INIT state"
    > and "flagged for synchronization" are exactly the same thing.
    >
    > SUGGESTION
    > A single sequencesync worker is responsible for synchronizing all
    > sequences. It begins by retrieving the list of sequences that are
    > flagged for needing synchronization (e.g. those with INIT state).
    >
    
    /e.g/i.e. We don't have multiple such states, so let's be specific.
    
    > ~~~
    >
    > 4.
    > Now that this function is in 2 parts, I think each part should be
    > clearly identified with comments, something like:
    >
    > PART 1:
    > /*
    >  * 1. Extract sequence information from the tuple slot received from the
    >  * publisher
    >  */
    >
    > PART 2:
    > /*
    >  * 2. Compare the remote sequence definition to the local sequence definition,
    >  * and report any discrepancies.
    >  */
    >
    
    I don't see the need for such explicit comments as the same is
    apparent from the code.
    
    > ~~~
    >
    > 5.
    > + seqinfo_local = (LogicalRepSequenceInfo *) list_nth(seqinfos, seqidx);
    > + seqinfo_local->found_on_pub = true;
    > + *seqinfo = seqinfo_local;
    >
    > Is this separate `seqinfo_local` variable needed? It seems always
    > unconditionally assigned to the parameter, so you might as well just
    > do without the extra variable. Maybe just rename the parameter as
    > `seqinfo_local`?
    >
    
    We can do without a local variable as well but it appears neat to
    modify and use local variable. I think it is a matter of personal
    choice, so either way is fine but I would prefer using local variable
    for this.
    
    >
    > 12.
    > There is still a yet-to-be-implemented test combination as previously
    > reported [1, comment #3], right?
    >
    
    I don't think adding similar negative tests adds value. So, we can skip those.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  459. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-10-31T05:56:31Z

    Hi Vignesh,
    
    For later.... here are some review comments for the documentation
    patch v20251030-0002
    
    ======
    doc/src/sgml/config.sgml
    
    wal_retrieve_retry_interval:
    
    1.
            <para>
    -        In logical replication, this parameter also limits how often a failing
    -        replication apply worker or table synchronization worker will be
    -        respawned.
    +        In logical replication, this parameter also limits how quickly a
    +        failing replication apply worker, table synchronization worker, or
    +        sequence synchronization worker will be respawned.
            </para>
    
    I think you can simplify that.
    
    SUGGESTION
    In logical replication, this parameter also limits how quickly a
    failing replication apply worker, or table/sequence synchronization
    worker will be respawned.
    
    ~~~
    
    max_logical_replication_workers:
    
    2.
            <para>
             Specifies maximum number of logical replication workers. This includes
    -        leader apply workers, parallel apply workers, and table synchronization
    -        workers.
    +        leader apply workers, parallel apply workers, table synchronization
    +        workers and a sequence synchronization worker.
            </para>
    
    I think you can simplify that.
    
    SUGGESTION
    This includes leader apply workers, parallel apply workers, and
    table/sequence synchronization workers.
    
    ~~~
    
    max_sync_workers_per_subscription:
    
    3.
            <para>
             Maximum number of synchronization workers per subscription. This
             parameter controls the amount of parallelism of the initial data copy
    -        during the subscription initialization or when new tables are added.
    +        during the subscription initialization or when new tables or sequences
    +        are added.
            </para>
    
    But, there is no parallelism at all for sequence copies, because there
    is only one sequencesync worker (as the following docs paragraph
    says), so maybe we do not need this docs change.
    
    NOTE -- see the comment #12 below, and maybe use wording like that.
    
    ======
    doc/src/sgml/logical-replication.sgml
    
    Section 29.1 Publication:
    
    4.
        Publications may currently only contain tables or sequences. Objects must be
        added explicitly, except when a publication is created using
        <literal>FOR TABLES IN SCHEMA</literal>, <literal>FOR ALL TABLES</literal>,
    -   or <literal>FOR ALL SEQUENCES</literal>.
    +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the state of
    +   sequences can be synchronized at any time. For more information, see
    +   <xref linkend="logical-replication-sequences"/>.
    
    Not sure about the wording "the state of". Maybe it can be simplified?
    
    SUGGESTION
    Unlike tables, sequences can be synchronized at any time.
    
    ~~~
    
    5.
    +    <listitem>
    +     <para>
    +      use <link linkend="sql-altersubscription-params-refresh-sequences">
    +      <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>
    +      to re-synchronize all sequences.
    +     </para>
    +    </listitem>
    
    AFAIK it's not going to get any newly added sequences so it is not
    really "all sequences" so this seems misleading. I thought it should
    be like below.
    
    SUGGESTION
    use ALTER SUBSCRIPTION ... REFRESH SEQUENCES to re-synchronize all
    sequences currently known to the subscription.
    
    ~~~
    
    Section 29.7.1. Sequence Definition Mismatches:
    
    6.
    +   <para>
    +    During sequence synchronization, the sequence definitions of the publisher
    +    and the subscriber are compared. An error is logged listing all differing
    +    sequences before the process exits. The apply worker detects this failure
    +    and repeatedly respawns the sequence synchronization worker to retry until
    +    all differences are resolved. See also
    +    <link linkend="guc-wal-retrieve-retry-interval"><varname>wal_retrieve_retry_interval</varname></link>.
    +   </para>
    
    It seems a bit misleading. e.g. AFAIK the "The apply worker detects
    this failure" is not true. IIUC, the apply worker simply finds some
    sequences that still have INIT state, so really it has no knowledge of
    failure at all, right?
    
    Consider rewording this part.
    
    SUGGESTION
    The sequence synchronization worker validates that sequence
    definitions match between publisher and subscriber. If mismatches
    exist, the worker logs an error identifying them and exits. The apply
    worker continues respawning the sequence synchronization worker until
    synchronization succeeds.
    
    ~~~
    
    Section 29.7.2. Refreshing Stale Sequences:
    
    7.
    +   <para>
    +    Subscriber side sequence values may frequently become out of sync due to
    +    updates on the publisher.
    +   </para>
    +   <para>
    +    To verify, compare the sequence values between the publisher and
    +    subscriber, and if necessary, execute
    +    <link linkend="sql-altersubscription-params-refresh-sequences">
    +    <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>.
    +   </para>
    
    I didn't see why the wording "To verify" was needed here. Below is a
    slightly simpler alternative for these paragraphs.
    
    SUGGESTION
    Subscriber sequence values drift out of sync as the publisher advances
    them.  Compare values between publisher and subscriber, then run ALTER
    SUBSCRIPTION ... REFRESH SEQUENCES to resynchronize if necessary.
    
    ~~~
    
    Section 29.7.3. Examples.
    
    8. GENERAL. Prompts in examples
    
    I think using prompts like "test_pub#" in the examples is frowned upon
    because it makes cutting directly from the examples more difficult.
    Similarly, the result of the commands is not shown.
    
    See other PG18 logical replication examples for why the current style
    is.... e.g. more like this:
    /* pub # */ CREATE TABLE t1(a int, b int, c text, PRIMARY KEY(a,c));
    /* pub # */ CREATE TABLE t2(d int, e int, f int, PRIMARY KEY(d));
    
    ~~~
    
    9.
    +    Re-synchronize all the sequences on the subscriber using
    +    <link linkend="sql-altersubscription-params-refresh-sequences">
    +    <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>.
    
    SUGGESTION
    Re-synchronize all sequences known to the subscriber using...
    
    ~~~
    
    Section 29.9. Restrictions #
    
    10.
    +     then this should typically not be a problem.  If, however, some kind of
    +     switchover or failover to the subscriber database is intended, then the
    +     sequences would need to be updated to the latest values, either by
    +     executing <link linkend="sql-altersubscription-params-refresh-sequences">
    +     <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>
    +     or by copying the current data from the publisher (perhaps using
    +     <command>pg_dump</command>) or by determining a sufficiently high value
    +     from the tables themselves.
    
    IIUC the "ALTER SUBSCRIPTION ... REFRESH SEQUENCES" is only going to
    resync the sequences that the subscriber already knew about. So, if
    you really wanted to get the latest of everything won't the user need
    to execute double-commands just in case there are some new sequences
    at the publisher?
    
    e.g.
    First, ALTER SUBSCRIPTION REFRESH PUBLICATION
    Then, ALTER SUBSCRIPTION REFRESH SEQUENCES
    
    ~~~
    
    Section 29.13.2. Subscribers #
    
    11.
    -    workers), plus some reserve for the table synchronization workers and
    -    parallel apply workers.
    +    workers), plus some reserve for the parallel apply workers, table
    synchronization workers, and a sequence
    +    synchronization worker.
    
    I think this can be worded similar to the config.sgml
    
    SUGGESTION
    ... plus some reserve for the parallel apply workers, and
    table/sequence synchronization workers.
    
    ~~
    
    12.
        <para>
         <link linkend="guc-max-sync-workers-per-subscription"><varname>max_sync_workers_per_subscription</varname></link>
    -     controls the amount of parallelism of the initial data copy during the
    -     subscription initialization or when new tables are added.
    +     controls how many tables can be synchronized in parallel during
    +     subscription initialization or when new tables are added. One additional
    +     worker is also needed for sequence synchronization.
        </para>
    
    Oh, perhaps this is the wording that should have been used in
    config.sgml (review comment #3) to avoid implying about sequencesync
    workers helping with parallelism.
    
    ======
    doc/src/sgml/monitoring.sgml
    
    13.
           <para>
            Type of the subscription worker process.  Possible types are
    -       <literal>apply</literal>, <literal>parallel apply</literal>, and
    -       <literal>table synchronization</literal>.
    +       <literal>apply</literal>, <literal>parallel apply</literal>,
    +       <literal>table synchronization</literal>, and
    +       <literal>sequence synchronization</literal>.
           </para></entry>
    
    This docs fragment probably belongs with the pg_stats patch, not here.
    
    ======
    doc/src/sgml/ref/create_subscription.sgml
    
    14.
               (see <xref linkend="sql-createtype"/> for more about send/receive
    -          functions).
    +          functions). This parameter is not applicable for sequences.
              </para>
    
    In many places for this page the patch says "This parameter is not
    applicable for sequences."
    
    IMO that is ambiguous. It is not clear if the parameter is silently
    ignored, if it will give an error, or what?
    
    Maybe you can clarify by saying "is ignored" or "has no effect",
    instead of "is not applicable"
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  460. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-01T05:15:41Z

    On Fri, 31 Oct 2025 at 07:34, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > Some review comments for v20251030-0001
    >
    > ======
    > Commit message
    >
    > 1.
    > 3) ALTER SUBSCRIPTION ... REFRESH SEQUENCES
    >     - (A new command introduced in PG19 by a prior patch.)
    >     - All sequences in pg_subscription_rel are reset to DATASYNC state.
    > ~
    >
    > DATASYNC? Just above, it says the only possible states for sequences
    > are INIT and READY.
    
    Modified
    
    > ======
    > .../replication/logical/sequencesync.c
    >
    > 2.
    > + * A single sequencesync worker is responsible for synchronizing all sequences
    > + * in INIT state in pg_subscription_rel. It begins by retrieving the list of
    > + * sequences flagged for synchronization. These sequences are then processed
    > + * in batches, allowing multiple entries to be synchronized within a single
    > + * transaction. The worker fetches the current sequence values and page LSNs
    > + * from the remote publisher, updates the corresponding sequences on the local
    > + * subscriber, and finally marks each sequence as READY upon successful
    > + * synchronization.
    > + *
    >
    > Those first 2 sentences seem repetitive because AFAIK "in INIT state"
    > and "flagged for synchronization" are exactly the same thing.
    >
    > SUGGESTION
    > A single sequencesync worker is responsible for synchronizing all
    > sequences. It begins by retrieving the list of sequences that are
    > flagged for needing synchronization (e.g. those with INIT state).
    
    Modified with slight changes
    
    > ~~~
    >
    > get_and_validate_seq_info:
    >
    > 3.
    > +/*
    > + * get_and_validate_seq_info
    > + *
    > + * Extracts remote sequence information from the tuple slot received from the
    > + * publisher and validates it against the corresponding local sequence
    > + * definition.
    > + */
    >
    > Missing comma.
    >
    > /publisher and validates/publisher, and validates/
    
    Modified
    
    > ~~~
    >
    > 4.
    > Now that this function is in 2 parts, I think each part should be
    > clearly identified with comments, something like:
    >
    > PART 1:
    > /*
    >  * 1. Extract sequence information from the tuple slot received from the
    >  * publisher
    >  */
    >
    > PART 2:
    > /*
    >  * 2. Compare the remote sequence definition to the local sequence definition,
    >  * and report any discrepancies.
    >  */
    
    I felt this is not required
    
    > ~~~
    >
    > 5.
    > + seqinfo_local = (LogicalRepSequenceInfo *) list_nth(seqinfos, seqidx);
    > + seqinfo_local->found_on_pub = true;
    > + *seqinfo = seqinfo_local;
    >
    > Is this separate `seqinfo_local` variable needed? It seems always
    > unconditionally assigned to the parameter, so you might as well just
    > do without the extra variable. Maybe just rename the parameter as
    > `seqinfo_local`?
    
    I preferred the existing as it is more readable
    
    > ~~~
    >
    > 6.
    > + if (!*sequence_rel) /* Sequence was concurrently dropped? */
    > + return COPYSEQ_SKIPPED;
    > +
    > + tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo_local->localrelid));
    > + if (!HeapTupleIsValid(tup)) /* Sequence was concurrently dropped? */
    > + return COPYSEQ_SKIPPED;
    >
    > Nit. IMO the code was easier to read in the previous patch version,
    > when it was commented above the code like:
    >
    > /* Sequence was concurrently dropped */
    > if (!*sequence_rel)
    >   return COPYSEQ_SKIPPED;
    >
    > /* Sequence was concurrently dropped */
    > tup = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seqinfo->localrelid));
    > if (!HeapTupleIsValid(tup))
    >   return COPYSEQ_SKIPPED;
    
    Updated
    
    > ~~~
    >
    > copy_sequence:
    >
    > 7.
    > +static CopySeqResult
    > +copy_sequence(LogicalRepSequenceInfo *seqinfo, int64 last_value,
    > +   bool is_called, XLogRecPtr page_lsn, Oid seqowner)
    > +{
    > + UserContext ucxt;
    > + AclResult aclresult;
    > + bool run_as_owner = MySubscription->runasowner;
    > + Oid seqoid = seqinfo->localrelid;
    > +
    > + /*
    > + * Make sure that the sequence is copied as sequence owner, unless the
    > + * user has opted out of that behaviour.
    > + */
    > + if (!run_as_owner)
    > + SwitchToUntrustedUser(seqowner, &ucxt);
    >
    > The code/comment seems contradictory because IMO it is vague what
    > runasowner member means -- which owner? AFAIK `run_as_owner` really
    > means "run as *subscription* owner". Ideally, the
    > MySubscription->runasowner member might be renamed to 'runassubowner'
    > but maybe that is a bigger change than you want to make for this
    > patch.
    >
    > So, maybe just the comment can be rewritten for more clarity.
    >
    > SUGGESTION:
    > If the user did not opt to run as the owner of the subscription
    > ('run_as_owner'), then copy the sequence as the owner of the sequence.
    >
    > (Also, make the similar comment change for the equivalent place in tablesync.c).
    
    Updated
    
    > ~~~
    >
    > copy_sequences:
    >
    > 8.
    > + ereport(LOG,
    > + errmsg("logical replication sequence synchronization for
    > subscription \"%s\" - total unsynchronized: %d",
    > +    MySubscription->name, list_length(seqinfos)));
    > +
    > + while (cur_batch_base_index < list_length(seqinfos))
    >
    > Would it be tidier to declare int n_seqinfos = list_length(seqinfos);
    > instead of using list_length() multiple times in this function.
    
    Modified
    
    > ~~~
    >
    > 9.
    > + * We deliberately avoid acquiring a local lock on the sequence before
    > + * querying the publisher to prevent potential distributed deadlocks
    > + * in bi-directional replication setups. For instance, a concurrent
    > + * ALTER SEQUENCE on one node might block this worker, while the
    > + * worker's own local lock simultaneously blocks a similar operation
    > + * on the other nod resulting in a circular wait that spans both nodes
    > + * and remains undetected.
    >
    > typo: /nod/node/
    
    Modified
    
    > ~~~
    >
    > 10.
    > + int64 last_value;
    > + bool is_called;
    > + XLogRecPtr page_lsn;
    > + CopySeqResult sync_status;
    > + LogicalRepSequenceInfo *seqinfo;
    > +
    > + CHECK_FOR_INTERRUPTS();
    > +
    > + if (ConfigReloadPending)
    > + {
    > + ConfigReloadPending = false;
    > + ProcessConfigFile(PGC_SIGHUP);
    > + }
    > +
    > + sync_status = get_and_validate_seq_info(slot, &sequence_rel,
    > + &seqinfo, &page_lsn,
    > + &last_value, &is_called);
    > + if (sync_status == COPYSEQ_SUCCESS)
    > + sync_status = copy_sequence(seqinfo, last_value, is_called,
    > + page_lsn,
    > + sequence_rel->rd_rel->relowner);
    >
    > Why does LogicalRepSequenceInfo only have to be metadata? Can't those
    > `page_lsn`, `last_value`, and `is_called` also be made members of
    > LogicalRepSequenceInfo, so you don't have to declare them and pass
    > them all in and out as parameters here?
    
    Modified
    
    > ======
    > src/test/subscription/t/036_sequences.pl
    >
    > 11.
    > +$node_publisher->safe_psql(
    > + 'postgres', qq(
    > + DROP SEQUENCE regress_s4;
    > +));
    > +
    > +# Verify that an error is logged for the missing sequence ('regress_s4').
    > +$node_subscriber->wait_for_log(
    > + qr/ERROR: ( [A-Z0-9]+:)? logical replication sequence
    > synchronization failed for subscription "regress_seq_sub"\n.*DETAIL:.*
    > Missing sequence\(s\) on publisher: \("public.regress_s4"\)/,
    > + $log_offset);
    >
    > I felt that psql DROP code belongs below the comment too.
    > Alternatively, add another comment for that DROP, like:
    > # Drop the sequence ('regress_s4') in preparation for the next test
    
    Modified
    
    > ~~~
    >
    > 12.
    > There is still a yet-to-be-implemented test combination as previously
    > reported [1, comment #3], right?
    
    I'm skipping this to keep minimal tests.
    
    Apart from these, the following improvements were done:
    a) The error message has been improved to split into 3 warning
    messages a) missing sequences b) mismatch sequences and insufficient
    privileges sequences and finally an error message as the original was
    too long and difficult to map each of the hints.
    b) errmsg_plural and errhint_plural were used for error messages to
    differentiate based on sequence/sequences based on sequence count.
    c) Changed the batch log message to debug1 level
    d) Few of the comments were improved to add more clarity.
    
    The attached v20251101 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  461. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-02T19:05:04Z

    On Fri, 31 Oct 2025 at 11:26, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > For later.... here are some review comments for the documentation
    > patch v20251030-0002
    >
    > ======
    > doc/src/sgml/config.sgml
    >
    > wal_retrieve_retry_interval:
    >
    > 1.
    >         <para>
    > -        In logical replication, this parameter also limits how often a failing
    > -        replication apply worker or table synchronization worker will be
    > -        respawned.
    > +        In logical replication, this parameter also limits how quickly a
    > +        failing replication apply worker, table synchronization worker, or
    > +        sequence synchronization worker will be respawned.
    >         </para>
    >
    > I think you can simplify that.
    >
    > SUGGESTION
    > In logical replication, this parameter also limits how quickly a
    > failing replication apply worker, or table/sequence synchronization
    > worker will be respawned.
    
    Modified
    
    > ~~~
    >
    > max_logical_replication_workers:
    >
    > 2.
    >         <para>
    >          Specifies maximum number of logical replication workers. This includes
    > -        leader apply workers, parallel apply workers, and table synchronization
    > -        workers.
    > +        leader apply workers, parallel apply workers, table synchronization
    > +        workers and a sequence synchronization worker.
    >         </para>
    >
    > I think you can simplify that.
    >
    > SUGGESTION
    > This includes leader apply workers, parallel apply workers, and
    > table/sequence synchronization workers.
    
    Modified
    
    > ~~~
    >
    > max_sync_workers_per_subscription:
    >
    > 3.
    >         <para>
    >          Maximum number of synchronization workers per subscription. This
    >          parameter controls the amount of parallelism of the initial data copy
    > -        during the subscription initialization or when new tables are added.
    > +        during the subscription initialization or when new tables or sequences
    > +        are added.
    >         </para>
    >
    > But, there is no parallelism at all for sequence copies, because there
    > is only one sequencesync worker (as the following docs paragraph
    > says), so maybe we do not need this docs change.
    >
    > NOTE -- see the comment #12 below, and maybe use wording like that.
    
    Modified similarly
    
    > ======
    > doc/src/sgml/logical-replication.sgml
    >
    > Section 29.1 Publication:
    >
    > 4.
    >     Publications may currently only contain tables or sequences. Objects must be
    >     added explicitly, except when a publication is created using
    >     <literal>FOR TABLES IN SCHEMA</literal>, <literal>FOR ALL TABLES</literal>,
    > -   or <literal>FOR ALL SEQUENCES</literal>.
    > +   or <literal>FOR ALL SEQUENCES</literal>. Unlike tables, the state of
    > +   sequences can be synchronized at any time. For more information, see
    > +   <xref linkend="logical-replication-sequences"/>.
    >
    > Not sure about the wording "the state of". Maybe it can be simplified?
    >
    > SUGGESTION
    > Unlike tables, sequences can be synchronized at any time.
    
    Modified
    
    > ~~~
    >
    > 5.
    > +    <listitem>
    > +     <para>
    > +      use <link linkend="sql-altersubscription-params-refresh-sequences">
    > +      <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>
    > +      to re-synchronize all sequences.
    > +     </para>
    > +    </listitem>
    >
    > AFAIK it's not going to get any newly added sequences so it is not
    > really "all sequences" so this seems misleading. I thought it should
    > be like below.
    >
    > SUGGESTION
    > use ALTER SUBSCRIPTION ... REFRESH SEQUENCES to re-synchronize all
    > sequences currently known to the subscription.
    
    Modified
    
    > ~~~
    >
    > Section 29.7.1. Sequence Definition Mismatches:
    >
    > 6.
    > +   <para>
    > +    During sequence synchronization, the sequence definitions of the publisher
    > +    and the subscriber are compared. An error is logged listing all differing
    > +    sequences before the process exits. The apply worker detects this failure
    > +    and repeatedly respawns the sequence synchronization worker to retry until
    > +    all differences are resolved. See also
    > +    <link linkend="guc-wal-retrieve-retry-interval"><varname>wal_retrieve_retry_interval</varname></link>.
    > +   </para>
    >
    > It seems a bit misleading. e.g. AFAIK the "The apply worker detects
    > this failure" is not true. IIUC, the apply worker simply finds some
    > sequences that still have INIT state, so really it has no knowledge of
    > failure at all, right?
    >
    > Consider rewording this part.
    >
    > SUGGESTION
    > The sequence synchronization worker validates that sequence
    > definitions match between publisher and subscriber. If mismatches
    > exist, the worker logs an error identifying them and exits. The apply
    > worker continues respawning the sequence synchronization worker until
    > synchronization succeeds.
    
    Modified
    
    > ~~~
    >
    > Section 29.7.2. Refreshing Stale Sequences:
    >
    > 7.
    > +   <para>
    > +    Subscriber side sequence values may frequently become out of sync due to
    > +    updates on the publisher.
    > +   </para>
    > +   <para>
    > +    To verify, compare the sequence values between the publisher and
    > +    subscriber, and if necessary, execute
    > +    <link linkend="sql-altersubscription-params-refresh-sequences">
    > +    <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>.
    > +   </para>
    >
    > I didn't see why the wording "To verify" was needed here. Below is a
    > slightly simpler alternative for these paragraphs.
    >
    > SUGGESTION
    > Subscriber sequence values drift out of sync as the publisher advances
    > them.  Compare values between publisher and subscriber, then run ALTER
    > SUBSCRIPTION ... REFRESH SEQUENCES to resynchronize if necessary.
    
    Modified
    
    > ~~~
    >
    > Section 29.7.3. Examples.
    >
    > 8. GENERAL. Prompts in examples
    >
    > I think using prompts like "test_pub#" in the examples is frowned upon
    > because it makes cutting directly from the examples more difficult.
    > Similarly, the result of the commands is not shown.
    >
    > See other PG18 logical replication examples for why the current style
    > is.... e.g. more like this:
    > /* pub # */ CREATE TABLE t1(a int, b int, c text, PRIMARY KEY(a,c));
    > /* pub # */ CREATE TABLE t2(d int, e int, f int, PRIMARY KEY(d));
    
    Modified
    
    > ~~~
    >
    > 9.
    > +    Re-synchronize all the sequences on the subscriber using
    > +    <link linkend="sql-altersubscription-params-refresh-sequences">
    > +    <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>.
    >
    > SUGGESTION
    > Re-synchronize all sequences known to the subscriber using...
    
    Modified
    
    > ~~~
    >
    > Section 29.9. Restrictions #
    >
    > 10.
    > +     then this should typically not be a problem.  If, however, some kind of
    > +     switchover or failover to the subscriber database is intended, then the
    > +     sequences would need to be updated to the latest values, either by
    > +     executing <link linkend="sql-altersubscription-params-refresh-sequences">
    > +     <command>ALTER SUBSCRIPTION ... REFRESH SEQUENCES</command></link>
    > +     or by copying the current data from the publisher (perhaps using
    > +     <command>pg_dump</command>) or by determining a sufficiently high value
    > +     from the tables themselves.
    >
    > IIUC the "ALTER SUBSCRIPTION ... REFRESH SEQUENCES" is only going to
    > resync the sequences that the subscriber already knew about. So, if
    > you really wanted to get the latest of everything won't the user need
    > to execute double-commands just in case there are some new sequences
    > at the publisher?
    >
    > e.g.
    > First, ALTER SUBSCRIPTION REFRESH PUBLICATION
    > Then, ALTER SUBSCRIPTION REFRESH SEQUENCES
    
    I felt we don't support DDL, so new one's created should be copied
    using pg_dump. I felt existing is ok.
    
    > ~~~
    >
    > Section 29.13.2. Subscribers #
    >
    > 11.
    > -    workers), plus some reserve for the table synchronization workers and
    > -    parallel apply workers.
    > +    workers), plus some reserve for the parallel apply workers, table
    > synchronization workers, and a sequence
    > +    synchronization worker.
    >
    > I think this can be worded similar to the config.sgml
    >
    > SUGGESTION
    > ... plus some reserve for the parallel apply workers, and
    > table/sequence synchronization workers.
    
    Modified
    
    > ~~
    >
    > 12.
    >     <para>
    >      <link linkend="guc-max-sync-workers-per-subscription"><varname>max_sync_workers_per_subscription</varname></link>
    > -     controls the amount of parallelism of the initial data copy during the
    > -     subscription initialization or when new tables are added.
    > +     controls how many tables can be synchronized in parallel during
    > +     subscription initialization or when new tables are added. One additional
    > +     worker is also needed for sequence synchronization.
    >     </para>
    >
    > Oh, perhaps this is the wording that should have been used in
    > config.sgml (review comment #3) to avoid implying about sequencesync
    > workers helping with parallelism.
    
    Used the sequence synchronization doc similar to here in #3
    
    > ======
    > doc/src/sgml/monitoring.sgml
    >
    > 13.
    >        <para>
    >         Type of the subscription worker process.  Possible types are
    > -       <literal>apply</literal>, <literal>parallel apply</literal>, and
    > -       <literal>table synchronization</literal>.
    > +       <literal>apply</literal>, <literal>parallel apply</literal>,
    > +       <literal>table synchronization</literal>, and
    > +       <literal>sequence synchronization</literal>.
    >        </para></entry>
    >
    > This docs fragment probably belongs with the pg_stats patch, not here.
    
    This is ok here as we display this for running process, the other
    stats patch is mainly for errors.
    
    > ======
    > doc/src/sgml/ref/create_subscription.sgml
    >
    > 14.
    >            (see <xref linkend="sql-createtype"/> for more about send/receive
    > -          functions).
    > +          functions). This parameter is not applicable for sequences.
    >           </para>
    >
    > In many places for this page the patch says "This parameter is not
    > applicable for sequences."
    >
    > IMO that is ambiguous. It is not clear if the parameter is silently
    > ignored, if it will give an error, or what?
    >
    > Maybe you can clarify by saying "is ignored" or "has no effect",
    > instead of "is not applicable"
    
    Modified
    
    The attached v20251102 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  462. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-11-03T11:14:34Z

    On Mon, Nov 3, 2025 at 12:35 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    
    Some inor comments on 0001.
    1.
    + /*
    + * Acquire LogicalRepWorkerLock in LW_EXCLUSIVE mode to block the apply
    + * worker (holding LW_SHARED) from reading or updating
    + * last_seqsync_start_time. See ProcessSyncingSequencesForApply().
    + */
    + LWLockAcquire(LogicalRepWorkerLock, LW_EXCLUSIVE);
    
    Is it required to have LW_EXCLUSIVE lock here? In the function
    ProcessSyncingSequencesForApply(), apply_worker access/update
    last_seqsync_start_time only once it ensures that sequence sync worker
    has exited. I have made changes related to this in the attached to
    show you what I have in mind.
    
    2.
    + /*
    + * Worker needs to process sequences across transaction boundary, so
    + * allocate them under long-lived context.
    + */
    + oldctx = MemoryContextSwitchTo(TopMemoryContext);
    +
    + seq = palloc0_object(LogicalRepSequenceInfo);
    …
    ...
    + /*
    + * Allocate in a long-lived memory context, since these
    + * errors will be reported after the transaction commits.
    + */
    + oldctx = MemoryContextSwitchTo(TopMemoryContext);
    + mismatched_seqs = lappend_int(mismatched_seqs, seqidx);
    
    At the above and other places in syncworker, we don't need to use
    TopMemoryContext; rather, we can use ApplyContext allocated via
    SequenceSyncWorkerMain()->SetupApplyOrSyncWorker()->InitializeLogRepWorker().
    
    3.
    ProcessSyncingTablesForApply(current_lsn);
    + ProcessSyncingSequencesForApply();
    
    I am not sure if the function name ProcessSyncingSequencesForApply is
    appropriate. For tables, we do some work for concurrently running
    tablesync workers and launch new as well but for sequences, we don't
    do any work for sequences that are already being synced. How about
    ProcessSequencesForSync()?
    
    4.
    +      /* Should never happen. */
    +      elog(ERROR, "Sequence synchronization worker not expected to
    process relations");
    
    The first letter of the ERROR message should be small. How about:
    "sequence synchronization worker is not expected to process
    relations"? I have made this change in the attached.
    
    5.
    @@ -5580,7 +5606,8 @@ start_apply(XLogRecPtr origin_startpos)
    * idle state.
    */
    AbortOutOfAnyTransaction();
    - pgstat_report_subscription_error(MySubscription->oid, !am_tablesync_worker());
    + pgstat_report_subscription_error(MySubscription->oid,
    + !am_tablesync_worker());
    
    Why this change?
    
    6.
    @@ -264,6 +267,8 @@ extern bool
    logicalrep_worker_launch(LogicalRepWorkerType wtype,
    Oid userid, Oid relid,
    dsm_handle subworker_dsm,
    bool retain_dead_tuples);
    +extern void launch_sync_worker(LogicalRepWorkerType wtype, int nsyncworkers,
    +    Oid relid, TimestampTz *last_start_time);
    extern void logicalrep_worker_stop(LogicalRepWorkerType wtype, Oid subid,
       Oid relid);
    All the other functions except the newly added one are from
    launcher.c. So, this one should be after those, no? It should be after
    the InvalidateSyncingRelStates() declaration.
    
    Apart from above, please find attached top-up patch to improve
    comments and some other cosmetic stuff. The 0001 patch looks good to
    me apart from the above minor points.
    
    -- 
    With Regards,
    Amit Kapila.
    
  463. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-03T15:16:10Z

    On Mon, 3 Nov 2025 at 16:44, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Mon, Nov 3, 2025 at 12:35 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    >
    > Some inor comments on 0001.
    > 1.
    > + /*
    > + * Acquire LogicalRepWorkerLock in LW_EXCLUSIVE mode to block the apply
    > + * worker (holding LW_SHARED) from reading or updating
    > + * last_seqsync_start_time. See ProcessSyncingSequencesForApply().
    > + */
    > + LWLockAcquire(LogicalRepWorkerLock, LW_EXCLUSIVE);
    >
    > Is it required to have LW_EXCLUSIVE lock here? In the function
    > ProcessSyncingSequencesForApply(), apply_worker access/update
    > last_seqsync_start_time only once it ensures that sequence sync worker
    > has exited. I have made changes related to this in the attached to
    > show you what I have in mind.
    
    Modified
    
    > 2.
    > + /*
    > + * Worker needs to process sequences across transaction boundary, so
    > + * allocate them under long-lived context.
    > + */
    > + oldctx = MemoryContextSwitchTo(TopMemoryContext);
    > +
    > + seq = palloc0_object(LogicalRepSequenceInfo);
    > …
    > ...
    > + /*
    > + * Allocate in a long-lived memory context, since these
    > + * errors will be reported after the transaction commits.
    > + */
    > + oldctx = MemoryContextSwitchTo(TopMemoryContext);
    > + mismatched_seqs = lappend_int(mismatched_seqs, seqidx);
    >
    > At the above and other places in syncworker, we don't need to use
    > TopMemoryContext; rather, we can use ApplyContext allocated via
    > SequenceSyncWorkerMain()->SetupApplyOrSyncWorker()->InitializeLogRepWorker().
    
    Modified
    
    > 3.
    > ProcessSyncingTablesForApply(current_lsn);
    > + ProcessSyncingSequencesForApply();
    >
    > I am not sure if the function name ProcessSyncingSequencesForApply is
    > appropriate. For tables, we do some work for concurrently running
    > tablesync workers and launch new as well but for sequences, we don't
    > do any work for sequences that are already being synced. How about
    > ProcessSequencesForSync()?
    
    Changed it to ProcessSequencesForSync
    
    > 4.
    > +      /* Should never happen. */
    > +      elog(ERROR, "Sequence synchronization worker not expected to
    > process relations");
    >
    > The first letter of the ERROR message should be small. How about:
    > "sequence synchronization worker is not expected to process
    > relations"? I have made this change in the attached.
    
    Modified
    
    > 5.
    > @@ -5580,7 +5606,8 @@ start_apply(XLogRecPtr origin_startpos)
    > * idle state.
    > */
    > AbortOutOfAnyTransaction();
    > - pgstat_report_subscription_error(MySubscription->oid, !am_tablesync_worker());
    > + pgstat_report_subscription_error(MySubscription->oid,
    > + !am_tablesync_worker());
    >
    > Why this change?
    
    This is not required, removed this change
    
    > 6.
    > @@ -264,6 +267,8 @@ extern bool
    > logicalrep_worker_launch(LogicalRepWorkerType wtype,
    > Oid userid, Oid relid,
    > dsm_handle subworker_dsm,
    > bool retain_dead_tuples);
    > +extern void launch_sync_worker(LogicalRepWorkerType wtype, int nsyncworkers,
    > +    Oid relid, TimestampTz *last_start_time);
    > extern void logicalrep_worker_stop(LogicalRepWorkerType wtype, Oid subid,
    >    Oid relid);
    > All the other functions except the newly added one are from
    > launcher.c. So, this one should be after those, no? It should be after
    > the InvalidateSyncingRelStates() declaration.
    
    Modified
    
    > Apart from above, please find attached top-up patch to improve
    > comments and some other cosmetic stuff.
    
    Thanks, I have merged them.
    
    The attached v20251103 patch has the changes for the same.
    
    Regards,
    Vignesh
    
  464. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-11-05T08:28:19Z

    On Mon, Nov 3, 2025 at 8:46 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > The attached v20251103 patch has the changes for the same.
    >
    
    I have pushed the 0001 after making minor adjustments in tests and at
    a few other places. Kindly rebase and send the remaining patches.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  465. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-11-05T09:41:20Z

    Please find a few comments on 003 patch (seqsync_error_count)
    
    1)
    + /*
    + * Report the worker failed during either sequence synchronization or
    + * table synchronization or apply.
    + */
    
    Shall we tweak it slightly to:
    Report the worker failed during sequence synchronization, table
    synchronization, or apply.
    
    2)
    
    + SELECT count(1) = 1 FROM pg_stat_subscription_stats
    + WHERE subname = '$sub_name' and seq_sync_error_count > 0 and
    sync_error_count > 0
      ])
        or die
        qq(Timed out while waiting for tablesync errors for subscription
    '$sub_name');
    
    Since we are checking both table-sync and seq-sync errors here, we
    shall update the failure-message.
    
    3)
    + # Change the sequence start value on the subscriber so that it
    doesn't error out.
    + $node_subscriber->safe_psql($db,
    + qq(ALTER SEQUENCE $sequence_name INCREMENT 1));
    
    Please mention in comment 'Change the sequence start value to default....'.
    Otherwise it is not clear why changing to 1 is helping here as the
    previous creation of seq on pub did not mention any 'INCREMENT' value
    at all.
    
    4)
    
    - # Wait for initial tablesync to finish.
    + # Wait for initial sync to finish.
      $node_subscriber->poll_query_until(
      $db,
      qq[
    - SELECT count(1) = 1 FROM pg_subscription_rel
    - WHERE srrelid = '$table_name'::regclass AND srsubstate in ('r', 's')
    + SELECT count(1) = 2 FROM pg_subscription_rel
    + WHERE srrelid IN ('$table_name'::regclass,
    '$sequence_name'::regclass) AND srsubstate in ('r', 's')
      ])
        or die
        qq(Timed out while waiting for subscriber to synchronize data for
    table '$table_name'.);
    
    
    a) Will it be better to separate the 2 queries as the table-sync can
    be 'r' and 's', while seq-sync has to be 'r'.
    
    b) If we plan to keep the same as above, the failure-message needs to
    be changed as it mentions only table.
    
    thanks
    Shveta
    
    
    
    
  466. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-05T12:27:12Z

    On Wed, 5 Nov 2025 at 13:58, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Mon, Nov 3, 2025 at 8:46 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached v20251103 patch has the changes for the same.
    > >
    >
    > I have pushed the 0001 after making minor adjustments in tests and at
    > a few other places. Kindly rebase and send the remaining patches.
    
    I noticed a buildfarm failure on prion at [1].
    The test failed on prion because it runs with the following additional
    configuration:
    log_error_verbosity = verbose
    
    Due to this setting, the logs include an extra LOCATION line between
    the WARNING and ERROR messages, which was not expected by the test:
    2025-11-05 11:35:21.090 UTC [1357163:3] WARNING:  55000: mismatched or
    renamed sequence on subscriber ("public.regress_s4")
    2025-11-05 11:35:21.090 UTC [1357163:4] LOCATION:
    report_sequence_errors, sequencesync.c:185
    2025-11-05 11:35:21.090 UTC [1357163:5] ERROR:  55000: logical
    replication sequence synchronization failed for subscription
    "regress_seq_sub"
    
    I'm working on a fix for this issue.
    
    [1] - https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=prion&dt=2025-11-05%2010%3A30%3A15
    
    Regards,
    Vignesh
    
    
    
    
  467. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-11-05T12:39:48Z

    On Wed, Nov 5, 2025 at 5:57 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Wed, 5 Nov 2025 at 13:58, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Mon, Nov 3, 2025 at 8:46 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > The attached v20251103 patch has the changes for the same.
    > > >
    > >
    > > I have pushed the 0001 after making minor adjustments in tests and at
    > > a few other places. Kindly rebase and send the remaining patches.
    >
    > I noticed a buildfarm failure on prion at [1].
    > The test failed on prion because it runs with the following additional
    > configuration:
    > log_error_verbosity = verbose
    >
    > Due to this setting, the logs include an extra LOCATION line between
    > the WARNING and ERROR messages, which was not expected by the test:
    > 2025-11-05 11:35:21.090 UTC [1357163:3] WARNING:  55000: mismatched or
    > renamed sequence on subscriber ("public.regress_s4")
    > 2025-11-05 11:35:21.090 UTC [1357163:4] LOCATION:
    > report_sequence_errors, sequencesync.c:185
    > 2025-11-05 11:35:21.090 UTC [1357163:5] ERROR:  55000: logical
    > replication sequence synchronization failed for subscription
    > "regress_seq_sub"
    >
    > I'm working on a fix for this issue.
    >
    
    We can fix it either by expecting just a WARNING for this test which
    is sufficient. The other possibility is that we can expect some other
    line(s) between WARNING and ERROR. I think just waiting for WARNING in
    the log is sufficient as that serves the purpose of this test. What do
    you think?
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  468. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-05T13:47:34Z

    On Wed, 5 Nov 2025 at 18:10, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Wed, Nov 5, 2025 at 5:57 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Wed, 5 Nov 2025 at 13:58, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > > >
    > > > On Mon, Nov 3, 2025 at 8:46 PM vignesh C <vignesh21@gmail.com> wrote:
    > > > >
    > > > > The attached v20251103 patch has the changes for the same.
    > > > >
    > > >
    > > > I have pushed the 0001 after making minor adjustments in tests and at
    > > > a few other places. Kindly rebase and send the remaining patches.
    > >
    > > I noticed a buildfarm failure on prion at [1].
    > > The test failed on prion because it runs with the following additional
    > > configuration:
    > > log_error_verbosity = verbose
    > >
    > > Due to this setting, the logs include an extra LOCATION line between
    > > the WARNING and ERROR messages, which was not expected by the test:
    > > 2025-11-05 11:35:21.090 UTC [1357163:3] WARNING:  55000: mismatched or
    > > renamed sequence on subscriber ("public.regress_s4")
    > > 2025-11-05 11:35:21.090 UTC [1357163:4] LOCATION:
    > > report_sequence_errors, sequencesync.c:185
    > > 2025-11-05 11:35:21.090 UTC [1357163:5] ERROR:  55000: logical
    > > replication sequence synchronization failed for subscription
    > > "regress_seq_sub"
    > >
    > > I'm working on a fix for this issue.
    > >
    >
    > We can fix it either by expecting just a WARNING for this test which
    > is sufficient. The other possibility is that we can expect some other
    > line(s) between WARNING and ERROR. I think just waiting for WARNING in
    > the log is sufficient as that serves the purpose of this test. What do
    > you think?
    
    I also think checking only for the WARNING message in the log is
    sufficient to verify the test. The attached patch includes this
    change.
    Alternatively, we could check for the WARNING first and then verify
    the ERROR separately if needed.
    Thoughts?
    
    Regards,
    Vignesh
    
  469. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-05T14:44:48Z

    On Wed, 5 Nov 2025 at 15:11, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > Please find a few comments on 003 patch (seqsync_error_count)
    >
    > 1)
    > + /*
    > + * Report the worker failed during either sequence synchronization or
    > + * table synchronization or apply.
    > + */
    >
    > Shall we tweak it slightly to:
    > Report the worker failed during sequence synchronization, table
    > synchronization, or apply.
    
    Modified
    
    > 2)
    >
    > + SELECT count(1) = 1 FROM pg_stat_subscription_stats
    > + WHERE subname = '$sub_name' and seq_sync_error_count > 0 and
    > sync_error_count > 0
    >   ])
    >     or die
    >     qq(Timed out while waiting for tablesync errors for subscription
    > '$sub_name');
    >
    > Since we are checking both table-sync and seq-sync errors here, we
    > shall update the failure-message.
    
    Modified
    
    > 3)
    > + # Change the sequence start value on the subscriber so that it
    > doesn't error out.
    > + $node_subscriber->safe_psql($db,
    > + qq(ALTER SEQUENCE $sequence_name INCREMENT 1));
    >
    > Please mention in comment 'Change the sequence start value to default....'.
    > Otherwise it is not clear why changing to 1 is helping here as the
    > previous creation of seq on pub did not mention any 'INCREMENT' value
    > at all.
    
    Modified
    
    > 4)
    >
    > - # Wait for initial tablesync to finish.
    > + # Wait for initial sync to finish.
    >   $node_subscriber->poll_query_until(
    >   $db,
    >   qq[
    > - SELECT count(1) = 1 FROM pg_subscription_rel
    > - WHERE srrelid = '$table_name'::regclass AND srsubstate in ('r', 's')
    > + SELECT count(1) = 2 FROM pg_subscription_rel
    > + WHERE srrelid IN ('$table_name'::regclass,
    > '$sequence_name'::regclass) AND srsubstate in ('r', 's')
    >   ])
    >     or die
    >     qq(Timed out while waiting for subscriber to synchronize data for
    > table '$table_name'.);
    >
    >
    > a) Will it be better to separate the 2 queries as the table-sync can
    > be 'r' and 's', while seq-sync has to be 'r'.
    >
    > b) If we plan to keep the same as above, the failure-message needs to
    > be changed as it mentions only table.
    
    I have separated the query to check individually for table sync and
    sequence sync.
    
    The attached v20251105 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  470. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-11-06T00:48:18Z

    Hi Vignesh,
    
    Some review comments for patch v20251105-0001 (stats counter)
    
    ======
    General.
    
    1.
    It was not obvious to me this counter is actually counting. Both the
    commit message and the docs say it counts "errors" during sequence
    synchronization. AFAIK the sequencesync worker processes sequences in
    "batches" of ~100, so in reality even if there are a dozen different
    sequences with problems, the worker combines them all and reports just
    one actual ERROR, doesn't it? So this counter appears to be just an
    indication that "something bad happened" during the synchronization.
    Even a high count value doesn't mean there are lots of sequences with
    errors; there might just be 1 sequence error that has remained
    unaddressed and so keeps incrementing the count every time the
    sequencesync reruns and re-fails, right?
    
    Maybe the descriptions can clarify what the counter really means?
    
    ======
    Commit message
    
    2.
    See general comment #1
    
    ======
    doc/src/sgml/monitoring.sgml
    
    sequence_sync_error_count:
    
    3.
    +      <para>
    +       Number of times an error occurred during the sequence synchronization
    +      </para></entry>
    
    See general comment #1
    
    ~~~
    
    sync_error_count:
    
    4.
    Now there are 2 kinds of synchronization workers -- tablesync and sequencesync.
    
    But there was already a stats counter called "sync_error_count". Are
    you worried that this name now seems ambiguous? (e.g. versus if it was
    called "table_sync_error_count"). How can we prevent users from being
    misled by this old generic looking name?
    
    ======
    src/backend/catalog/system_views.sql
    
    5.
             ss.apply_error_count,
    +        ss.seq_sync_error_count,
             ss.sync_error_count,
    
    The documentation said the new column was called "sequence_sync_error_count".
    
    ======
    src/backend/utils/adt/pgstatfuncs.c
    
    pg_stat_get_subscription_stats:
    
    6.
    - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "sync_error_count",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "seq_sync_error_count",
         INT8OID, -1, 0);
    - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "confl_insert_exists",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "sync_error_count",
         INT8OID, -1, 0);
    - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "confl_update_origin_differs",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "confl_insert_exists",
         INT8OID, -1, 0);
    - TupleDescInitEntry(tupdesc, (AttrNumber) 6, "confl_update_exists",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "confl_update_origin_differs",
         INT8OID, -1, 0);
    - TupleDescInitEntry(tupdesc, (AttrNumber) 7, "confl_update_deleted",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 7, "confl_update_exists",
         INT8OID, -1, 0);
    - TupleDescInitEntry(tupdesc, (AttrNumber) 8, "confl_update_missing",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 8, "confl_update_deleted",
         INT8OID, -1, 0);
    - TupleDescInitEntry(tupdesc, (AttrNumber) 9, "confl_delete_origin_differs",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 9, "confl_update_missing",
         INT8OID, -1, 0);
    - TupleDescInitEntry(tupdesc, (AttrNumber) 10, "confl_delete_missing",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 10, "confl_delete_origin_differs",
         INT8OID, -1, 0);
    - TupleDescInitEntry(tupdesc, (AttrNumber) 11,
    "confl_multiple_unique_conflicts",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 11, "confl_delete_missing",
         INT8OID, -1, 0);
    - TupleDescInitEntry(tupdesc, (AttrNumber) 12, "stats_reset",
    + TupleDescInitEntry(tupdesc, (AttrNumber) 12,
    "confl_multiple_unique_conflicts",
    +    INT8OID, -1, 0);
    + TupleDescInitEntry(tupdesc, (AttrNumber) 13, "stats_reset",
    
    6a.
    IMO now is a good opportunity to make more use of that 'i' variable,
    instead of hardwiring all the column indexes 1,2,3...13. That way
    would avoid all this code churn every time a new stats column gets
    added in the future.
    
    ~
    
    6b.
    The documentation said the new column was called "sequence_sync_error_count".
    
    ======
    src/test/subscription/t/026_stats.pl
    
    7.
     sub create_sub_pub_w_errors
     {
    - my ($node_publisher, $node_subscriber, $db, $table_name) = @_;
    + my ($node_publisher, $node_subscriber, $db, $table_name, $sequence_name)
    +   = @_;
      # Initial table setup on both publisher and subscriber. On subscriber we
      # create the same tables but with primary keys. Also, insert some data that
      # will conflict with the data replicated from publisher later.
    
    ~
    
    I think that comment should also mention that you've made a subscriber
    SEQUENCE with a different INCREMENT to deliberately clash with the
    publisher sequence of the same name.
    
    Also typos:
    /On subscriber/On the subscriber/
    /from publisher/from the publisher/
    
    ~~~
    
    8.
    + # Change the sequence start value back to the default on the subscriber so
    + # it doesn't error out.
    + $node_subscriber->safe_psql($db,
    + qq(ALTER SEQUENCE $sequence_name INCREMENT 1));
    +
    
    That comment is not quite right. e.g. you are changing the INCREMENT
    to match, not the "start value".
    
    ~~~
    
    9.
    - # Wait for initial tablesync to finish.
    + # Wait for initial tablesync sync to finish.
    
    "tablesync sync"?
    
    Was this change needed at all? If any change is needed at all (I am
    not saying it is) I thought it should say something more like: "Wait
    for the initial tablesync to finish successfully."
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  471. Re: Logical Replication of sequences

    Shinya Kato <shinya11.kato@gmail.com> — 2025-11-06T02:29:31Z

    On Wed, Nov 5, 2025 at 5:28 PM Amit Kapila <amit.kapila16@gmail.com> wrote:
    > I have pushed the 0001 after making minor adjustments in tests and at
    > a few other places. Kindly rebase and send the remaining patches.
    
    I discovered that the sequence sync worker fails for sequences
    containing single quotes.
    ---
    2025-11-06 10:22:50.335 JST [1096008] ERROR:  could not fetch sequence
    information from the publisher: ERROR:  syntax error at or near
    "quote"
            LINE 4: FROM ( VALUES ('public', 'regress'quote', 0), ('public', 'ho...
                                                      ^
    2025-11-06 10:22:50.335 JST [1088168] LOG:  background worker "logical
    replication sequencesync worker" (PID 1096008) exited with exit code 1
    ---
    
    I haven't read all the threads, so I might be mistaken, but I've
    created a patch.
    
    
    -- 
    Best regards,
    Shinya Kato
    NTT OSS Center
    
  472. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-11-06T04:40:23Z

    On Thu, Nov 6, 2025 at 8:00 AM Shinya Kato <shinya11.kato@gmail.com> wrote:
    >
    >
    > I discovered that the sequence sync worker fails for sequences
    > containing single quotes.
    > ---
    > 2025-11-06 10:22:50.335 JST [1096008] ERROR:  could not fetch sequence
    > information from the publisher: ERROR:  syntax error at or near
    > "quote"
    >         LINE 4: FROM ( VALUES ('public', 'regress'quote', 0), ('public', 'ho...
    >                                                   ^
    > 2025-11-06 10:22:50.335 JST [1088168] LOG:  background worker "logical
    > replication sequencesync worker" (PID 1096008) exited with exit code 1
    > ---
    >
    > I haven't read all the threads, so I might be mistaken, but I've
    > created a patch.
    >
    
    Thanks for spotting the issue and providing a fix. Here are few comments:
    
    1.
    + nsp_literal = quote_literal_cstr(seqinfo->nspname);
    + seq_literal = quote_literal_cstr(seqinfo->seqname);
    +
    + appendStringInfo(seqstr, "(%s, %s, %d)",
    + nsp_literal, seq_literal, idx);
    +
    + pfree(nsp_literal);
    + pfree(seq_literal);
    
    We don't need this retail pfree as the current memory context at this
    place will be TopTransactionContext that will anyway be freed after a
    batch of sequences.
    
    2.
    @@ -147,13 +148,18 @@ get_sequences_string(List *seqindexes, StringInfo buf)
      resetStringInfo(buf);
      foreach_int(seqidx, seqindexes)
      {
    + char *qualified_name;
    +
      LogicalRepSequenceInfo *seqinfo =
      (LogicalRepSequenceInfo *) list_nth(seqinfos, seqidx);
    
      if (buf->len > 0)
      appendStringInfoString(buf, ", ");
    
    - appendStringInfo(buf, "\"%s.%s\"", seqinfo->nspname, seqinfo->seqname);
    + qualified_name = quote_qualified_identifier(seqinfo->nspname,
    + seqinfo->seqname);
    + appendStringInfoString(buf, qualified_name);
    
    The function get_sequences_string() is used in WARNING code path and
    normally we don't quote names in messages. For example, see following
    cases:
    
    parserOpenTable:
    ereport(ERROR,
        (errcode(ERRCODE_UNDEFINED_TABLE),
        errmsg("relation \"%s.%s\" does not exist",
            relation->schemaname, relation->relname)));
    
    
    
    RangeVarGetRelidExtended:
            ereport(elevel,
                (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
                 errmsg("could not obtain lock on relation \"%s.%s\"",
                    relation->schemaname, relation->relname)));
    
    3. Also, see, if the newly added test can be combined with other existing tests.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  473. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-06T05:18:27Z

    On Thu, 6 Nov 2025 at 10:10, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Nov 6, 2025 at 8:00 AM Shinya Kato <shinya11.kato@gmail.com> wrote:
    > >
    > >
    > > I discovered that the sequence sync worker fails for sequences
    > > containing single quotes.
    > > ---
    > > 2025-11-06 10:22:50.335 JST [1096008] ERROR:  could not fetch sequence
    > > information from the publisher: ERROR:  syntax error at or near
    > > "quote"
    > >         LINE 4: FROM ( VALUES ('public', 'regress'quote', 0), ('public', 'ho...
    > >                                                   ^
    > > 2025-11-06 10:22:50.335 JST [1088168] LOG:  background worker "logical
    > > replication sequencesync worker" (PID 1096008) exited with exit code 1
    > > ---
    > >
    > > I haven't read all the threads, so I might be mistaken, but I've
    > > created a patch.
    
    Thanks Kato-san for finding this issue and sharing the changes.
    
    >
    > 1.
    > + nsp_literal = quote_literal_cstr(seqinfo->nspname);
    > + seq_literal = quote_literal_cstr(seqinfo->seqname);
    > +
    > + appendStringInfo(seqstr, "(%s, %s, %d)",
    > + nsp_literal, seq_literal, idx);
    > +
    > + pfree(nsp_literal);
    > + pfree(seq_literal);
    >
    > We don't need this retail pfree as the current memory context at this
    > place will be TopTransactionContext that will anyway be freed after a
    > batch of sequences.
    
    Modified
    
    > 2.
    > @@ -147,13 +148,18 @@ get_sequences_string(List *seqindexes, StringInfo buf)
    >   resetStringInfo(buf);
    >   foreach_int(seqidx, seqindexes)
    >   {
    > + char *qualified_name;
    > +
    >   LogicalRepSequenceInfo *seqinfo =
    >   (LogicalRepSequenceInfo *) list_nth(seqinfos, seqidx);
    >
    >   if (buf->len > 0)
    >   appendStringInfoString(buf, ", ");
    >
    > - appendStringInfo(buf, "\"%s.%s\"", seqinfo->nspname, seqinfo->seqname);
    > + qualified_name = quote_qualified_identifier(seqinfo->nspname,
    > + seqinfo->seqname);
    > + appendStringInfoString(buf, qualified_name);
    >
    > The function get_sequences_string() is used in WARNING code path and
    > normally we don't quote names in messages. For example, see following
    > cases:
    
    Agree on this.
    
    > 3. Also, see, if the newly added test can be combined with other existing tests.
    
    Modified
    
    The patch also includes the change for buildfarm failure at [1].
    [1] - https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=prion&dt=2025-11-05%2010%3A30%3A15
    
    The attached v2 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  474. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-11-06T10:37:32Z

    On Thu, Nov 6, 2025 at 10:48 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > The patch also includes the change for buildfarm failure at [1].
    > [1] - https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=prion&dt=2025-11-05%2010%3A30%3A15
    >
    > The attached v2 version patch has the changes for the same.
    >
    
    Thanks for the patch, Pushed.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  475. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-07T05:28:19Z

    On Thu, 6 Nov 2025 at 16:07, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Nov 6, 2025 at 10:48 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The patch also includes the change for buildfarm failure at [1].
    > > [1] - https://buildfarm.postgresql.org/cgi-bin/show_log.pl?nm=prion&dt=2025-11-05%2010%3A30%3A15
    > >
    > > The attached v2 version patch has the changes for the same.
    > >
    >
    > Thanks for the patch, Pushed.
    
    Thanks for pushing the patch, here is a rebased version of the
    remaining patches.
    
    This patch also addresses Peter's comments at [1 except the 4th
    comment (renaming existing column) for which I will post a patch
    separately.
    [1] - https://www.postgresql.org/message-id/CAHut%2BPtoLN0bRu7bNiSeF04dQQecoW-EXKMBX%3DHy0uqCvQa8MA%40mail.gmail.com
    
    Regards,
    Vignesh
    
  476. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-11-07T09:23:55Z

    On Fri, Nov 7, 2025 at 10:58 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    >
    > Thanks for pushing the patch, here is a rebased version of the
    > remaining patches.
    >
    
    Please find a few comments on doc patch:
    
    1)
    +    them. To verify this, compare the
    +    <link linkend="catalog-pg-subscription-rel">pg_subscription_rel</link>.<structfield>srsublsn</structfield>
    +    on the subscriber with the page_lsn obtained from the
    +    <function>pg_get_sequence_data</function> for the sequence on the
    publisher.
    
    Is there a way to give link of 'pg_get_sequence_data' here?
    
    2)
    +   <warning>
    +    <para>
    +     Each sequence caches a block of values (typically 32) in memory before
    +     generating a new WAL record, so its LSN advances only after the entire
    +     cached batch has been consumed. As a result, sequence value
    drift cannot be
    +     detected by comparing LSNs for sequence increments that fall within the
    +     same cached block.
    +    </para>
    +   </warning>
    
    In such a case, shall we mention that compare last_value to see the
    drift? Thoughts?
    
    3)
    
    +    To detect this, compare the
    +    <link linkend="catalog-pg-subscription-rel">pg_subscription_rel</link>.<structfield>srsublsn</structfield>
    +    on the subscriber with the page_lsn obtained from the
    +    <function>pg_get_sequence_data</function> for the sequence on the
    publisher.
    
    
    We have mentioned above. But in the example of the same, we do not
    show srsublsn or page_lsn anywhere. Shall we query and show that as
    well?
    
    
    4)
             Maximum number of synchronization workers per subscription. This
             parameter controls the amount of parallelism of the initial data copy
             during the subscription initialization or when new tables are added.
    +        One additional worker is also needed for sequence synchronization.
            </para>
    
    Since now the first line is talking only about table-sync, shall we tweak it:
    'of the initial data copy' --> 'of the initial data copy for tables'
    
    5)
    +        Returns information about the sequence. <literal>last_value</literal>
    +        indicates last sequence value set in sequence by nextval or setval,
    
    last_value can also be set by seq synchronization. Do you think that
    we need to mention that or current info is good enough?
    
    thanks
    Shveta
    
    
    
    
  477. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-11-07T11:29:51Z

    On Fri, Nov 7, 2025 at 10:58 AM vignesh C <vignesh21@gmail.com> wrote:
    >
    > Thanks for pushing the patch, here is a rebased version of the
    > remaining patches.
    >
    
    Pushed after reverting change related to converting fixed offset to a
    counter based scheme for view columns. We use the same method (fixed
    column numbers) in most other exposed functions, so kept the same for
    the sake of consistency.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  478. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-07T14:47:57Z

    On Fri, 7 Nov 2025 at 14:54, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Fri, Nov 7, 2025 at 10:58 AM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > >
    > > Thanks for pushing the patch, here is a rebased version of the
    > > remaining patches.
    > >
    >
    > Please find a few comments on doc patch:
    >
    > 1)
    > +    them. To verify this, compare the
    > +    <link linkend="catalog-pg-subscription-rel">pg_subscription_rel</link>.<structfield>srsublsn</structfield>
    > +    on the subscriber with the page_lsn obtained from the
    > +    <function>pg_get_sequence_data</function> for the sequence on the
    > publisher.
    >
    > Is there a way to give link of 'pg_get_sequence_data' here?
    
    Modified
    
    > 2)
    > +   <warning>
    > +    <para>
    > +     Each sequence caches a block of values (typically 32) in memory before
    > +     generating a new WAL record, so its LSN advances only after the entire
    > +     cached batch has been consumed. As a result, sequence value
    > drift cannot be
    > +     detected by comparing LSNs for sequence increments that fall within the
    > +     same cached block.
    > +    </para>
    > +   </warning>
    >
    > In such a case, shall we mention that compare last_value to see the
    > drift? Thoughts?
    
    I was not sure as it might not be very efficient
    
    > 3)
    >
    > +    To detect this, compare the
    > +    <link linkend="catalog-pg-subscription-rel">pg_subscription_rel</link>.<structfield>srsublsn</structfield>
    > +    on the subscriber with the page_lsn obtained from the
    > +    <function>pg_get_sequence_data</function> for the sequence on the
    > publisher.
    >
    >
    > We have mentioned above. But in the example of the same, we do not
    > show srsublsn or page_lsn anywhere. Shall we query and show that as
    > well?
    
    Updated example
    
    >
    > 4)
    >          Maximum number of synchronization workers per subscription. This
    >          parameter controls the amount of parallelism of the initial data copy
    >          during the subscription initialization or when new tables are added.
    > +        One additional worker is also needed for sequence synchronization.
    >         </para>
    >
    > Since now the first line is talking only about table-sync, shall we tweak it:
    > 'of the initial data copy' --> 'of the initial data copy for tables'
    
    Modified
    
    > 5)
    > +        Returns information about the sequence. <literal>last_value</literal>
    > +        indicates last sequence value set in sequence by nextval or setval,
    >
    > last_value can also be set by seq synchronization. Do you think that
    > we need to mention that or current info is good enough?
    
    Updated
    
    The attached v20251107_2 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  479. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2025-11-10T09:03:54Z

    On Fri, 7 Nov 2025 at 20:18, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Fri, 7 Nov 2025 at 14:54, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Fri, Nov 7, 2025 at 10:58 AM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > >
    > > > Thanks for pushing the patch, here is a rebased version of the
    > > > remaining patches.
    > > >
    > >
    > > Please find a few comments on doc patch:
    > >
    > > 1)
    > > +    them. To verify this, compare the
    > > +    <link linkend="catalog-pg-subscription-rel">pg_subscription_rel</link>.<structfield>srsublsn</structfield>
    > > +    on the subscriber with the page_lsn obtained from the
    > > +    <function>pg_get_sequence_data</function> for the sequence on the
    > > publisher.
    > >
    > > Is there a way to give link of 'pg_get_sequence_data' here?
    >
    > Modified
    >
    > > 2)
    > > +   <warning>
    > > +    <para>
    > > +     Each sequence caches a block of values (typically 32) in memory before
    > > +     generating a new WAL record, so its LSN advances only after the entire
    > > +     cached batch has been consumed. As a result, sequence value
    > > drift cannot be
    > > +     detected by comparing LSNs for sequence increments that fall within the
    > > +     same cached block.
    > > +    </para>
    > > +   </warning>
    > >
    > > In such a case, shall we mention that compare last_value to see the
    > > drift? Thoughts?
    >
    > I was not sure as it might not be very efficient
    >
    > > 3)
    > >
    > > +    To detect this, compare the
    > > +    <link linkend="catalog-pg-subscription-rel">pg_subscription_rel</link>.<structfield>srsublsn</structfield>
    > > +    on the subscriber with the page_lsn obtained from the
    > > +    <function>pg_get_sequence_data</function> for the sequence on the
    > > publisher.
    > >
    > >
    > > We have mentioned above. But in the example of the same, we do not
    > > show srsublsn or page_lsn anywhere. Shall we query and show that as
    > > well?
    >
    > Updated example
    >
    > >
    > > 4)
    > >          Maximum number of synchronization workers per subscription. This
    > >          parameter controls the amount of parallelism of the initial data copy
    > >          during the subscription initialization or when new tables are added.
    > > +        One additional worker is also needed for sequence synchronization.
    > >         </para>
    > >
    > > Since now the first line is talking only about table-sync, shall we tweak it:
    > > 'of the initial data copy' --> 'of the initial data copy for tables'
    >
    > Modified
    >
    > > 5)
    > > +        Returns information about the sequence. <literal>last_value</literal>
    > > +        indicates last sequence value set in sequence by nextval or setval,
    > >
    > > last_value can also be set by seq synchronization. Do you think that
    > > we need to mention that or current info is good enough?
    >
    > Updated
    >
    > The attached v20251107_2 version patch has the changes for the same.
    >
    Hi Vignesh,
    
    While working on another thread, I found that in HEAD gram.y has
    grammar which was committed as part of this thread:
    ```
                | CREATE PUBLICATION name FOR pub_obj_type_list opt_definition
                    {
                        CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
    
                        n->pubname = $3;
                        n->pubobjects = (List *) $5;
                        preprocess_pub_all_objtype_list($5, &n->for_all_tables,
                                                        &n->for_all_sequences,
                                                        yyscanner);
                        n->options = $6;
                        $$ = (Node *) n;
                    }
    ```
    
    Here we are assigning "n->pubobjects = (List *) $5". But later in the
    code this is not used anywhere for ALL TABLES/ ALL SEQUENCES
    publication. It is used for other publications (not ALL TABLES/
    SEQUENCES) inside function "ObjectsInPublicationToOids"
    
    So are we required to assign "n->pubobjects" here?
    
    I have created a patch to remove this assignment. It passed "make check-world".
    
    Thanks,
    Shlok Kyal
    
  480. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-10T10:52:15Z

    On Mon, 10 Nov 2025 at 14:34, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    >
    > While working on another thread, I found that in HEAD gram.y has
    > grammar which was committed as part of this thread:
    > ```
    >             | CREATE PUBLICATION name FOR pub_obj_type_list opt_definition
    >                 {
    >                     CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
    >
    >                     n->pubname = $3;
    >                     n->pubobjects = (List *) $5;
    >                     preprocess_pub_all_objtype_list($5, &n->for_all_tables,
    >                                                     &n->for_all_sequences,
    >                                                     yyscanner);
    >                     n->options = $6;
    >                     $$ = (Node *) n;
    >                 }
    > ```
    >
    > Here we are assigning "n->pubobjects = (List *) $5". But later in the
    > code this is not used anywhere for ALL TABLES/ ALL SEQUENCES
    > publication. It is used for other publications (not ALL TABLES/
    > SEQUENCES) inside function "ObjectsInPublicationToOids"
    >
    > So are we required to assign "n->pubobjects" here?
    >
    > I have created a patch to remove this assignment. It passed "make check-world".
    
    I agree that this is not required for ALL TABLES/ALL SEQUENCES cases.
    Your changes look good to me.
    
    Regards,
    Vignesh
    
    
    
    
  481. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-11-11T03:32:41Z

    On Mon, Nov 10, 2025 at 4:22 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Mon, 10 Nov 2025 at 14:34, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    > >
    > > While working on another thread, I found that in HEAD gram.y has
    > > grammar which was committed as part of this thread:
    > > ```
    > >             | CREATE PUBLICATION name FOR pub_obj_type_list opt_definition
    > >                 {
    > >                     CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
    > >
    > >                     n->pubname = $3;
    > >                     n->pubobjects = (List *) $5;
    > >                     preprocess_pub_all_objtype_list($5, &n->for_all_tables,
    > >                                                     &n->for_all_sequences,
    > >                                                     yyscanner);
    > >                     n->options = $6;
    > >                     $$ = (Node *) n;
    > >                 }
    > > ```
    > >
    > > Here we are assigning "n->pubobjects = (List *) $5". But later in the
    > > code this is not used anywhere for ALL TABLES/ ALL SEQUENCES
    > > publication. It is used for other publications (not ALL TABLES/
    > > SEQUENCES) inside function "ObjectsInPublicationToOids"
    > >
    > > So are we required to assign "n->pubobjects" here?
    > >
    > > I have created a patch to remove this assignment. It passed "make check-world".
    >
    > I agree that this is not required for ALL TABLES/ALL SEQUENCES cases.
    >
    
    I also agree. BTW, can we change pub_obj_type_list to
    pub_all_obj_type_list to be more explicit about this variant? If you
    agree then we can make similar changes
    (pub_obj_type->pub_all_obj_type) at the following places as well:
    
    + * CREATE PUBLICATION FOR ALL pub_obj_type [, ...] [WITH options]
    + *
    + * pub_obj_type is one of:
    + *
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  482. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2025-11-11T04:28:50Z

    On Tue, 11 Nov 2025 at 09:02, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Mon, Nov 10, 2025 at 4:22 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Mon, 10 Nov 2025 at 14:34, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    > > >
    > > > While working on another thread, I found that in HEAD gram.y has
    > > > grammar which was committed as part of this thread:
    > > > ```
    > > >             | CREATE PUBLICATION name FOR pub_obj_type_list opt_definition
    > > >                 {
    > > >                     CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
    > > >
    > > >                     n->pubname = $3;
    > > >                     n->pubobjects = (List *) $5;
    > > >                     preprocess_pub_all_objtype_list($5, &n->for_all_tables,
    > > >                                                     &n->for_all_sequences,
    > > >                                                     yyscanner);
    > > >                     n->options = $6;
    > > >                     $$ = (Node *) n;
    > > >                 }
    > > > ```
    > > >
    > > > Here we are assigning "n->pubobjects = (List *) $5". But later in the
    > > > code this is not used anywhere for ALL TABLES/ ALL SEQUENCES
    > > > publication. It is used for other publications (not ALL TABLES/
    > > > SEQUENCES) inside function "ObjectsInPublicationToOids"
    > > >
    > > > So are we required to assign "n->pubobjects" here?
    > > >
    > > > I have created a patch to remove this assignment. It passed "make check-world".
    > >
    > > I agree that this is not required for ALL TABLES/ALL SEQUENCES cases.
    > >
    >
    > I also agree. BTW, can we change pub_obj_type_list to
    > pub_all_obj_type_list to be more explicit about this variant? If you
    > agree then we can make similar changes
    > (pub_obj_type->pub_all_obj_type) at the following places as well:
    >
    > + * CREATE PUBLICATION FOR ALL pub_obj_type [, ...] [WITH options]
    > + *
    > + * pub_obj_type is one of:
    > + *
    >
    Hi Vignesh, Amit
    
    Thanks for confirming.
    Also, I agree that the name 'pub_all_obj_type' will be more suitable.
    I have updated the patch for the same.
    
    Thanks,
    Shlok Kyal
    
  483. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-11T05:46:18Z

    On Tue, 11 Nov 2025 at 09:59, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    >
    > On Tue, 11 Nov 2025 at 09:02, Amit Kapila <amit.kapila16@gmail.com> wrote:
    > >
    > > On Mon, Nov 10, 2025 at 4:22 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Mon, 10 Nov 2025 at 14:34, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    > > > >
    > > > > While working on another thread, I found that in HEAD gram.y has
    > > > > grammar which was committed as part of this thread:
    > > > > ```
    > > > >             | CREATE PUBLICATION name FOR pub_obj_type_list opt_definition
    > > > >                 {
    > > > >                     CreatePublicationStmt *n = makeNode(CreatePublicationStmt);
    > > > >
    > > > >                     n->pubname = $3;
    > > > >                     n->pubobjects = (List *) $5;
    > > > >                     preprocess_pub_all_objtype_list($5, &n->for_all_tables,
    > > > >                                                     &n->for_all_sequences,
    > > > >                                                     yyscanner);
    > > > >                     n->options = $6;
    > > > >                     $$ = (Node *) n;
    > > > >                 }
    > > > > ```
    > > > >
    > > > > Here we are assigning "n->pubobjects = (List *) $5". But later in the
    > > > > code this is not used anywhere for ALL TABLES/ ALL SEQUENCES
    > > > > publication. It is used for other publications (not ALL TABLES/
    > > > > SEQUENCES) inside function "ObjectsInPublicationToOids"
    > > > >
    > > > > So are we required to assign "n->pubobjects" here?
    > > > >
    > > > > I have created a patch to remove this assignment. It passed "make check-world".
    > > >
    > > > I agree that this is not required for ALL TABLES/ALL SEQUENCES cases.
    > > >
    > >
    > > I also agree. BTW, can we change pub_obj_type_list to
    > > pub_all_obj_type_list to be more explicit about this variant? If you
    > > agree then we can make similar changes
    > > (pub_obj_type->pub_all_obj_type) at the following places as well:
    > >
    > > + * CREATE PUBLICATION FOR ALL pub_obj_type [, ...] [WITH options]
    > > + *
    > > + * pub_obj_type is one of:
    > > + *
    > >
    > Hi Vignesh, Amit
    >
    > Thanks for confirming.
    > Also, I agree that the name 'pub_all_obj_type' will be more suitable.
    > I have updated the patch for the same.
    
    Thanks, this version looks good to me, I don't have any comments.
    
    Regards,
    Vignesh
    
    
    
    
  484. Re: Logical Replication of sequences

    Chao Li <li.evan.chao@gmail.com> — 2025-11-11T05:52:21Z

    Hi Vignesh,
    
    A few more comments:
    
    > On Nov 7, 2025, at 22:47, vignesh C <vignesh21@gmail.com> wrote:
    > 
    > The attached v20251107_2 version patch has the changes for the same.
    > 
    > Regards,
    > Vignesh
    > <v20251107_2-0001-Documentation-for-sequence-synchronizati.patch>
    
    1
    ```
    -        Currently, there can be only one synchronization worker per table.
    +        Currently, there can be only one table synchronization worker per table
    +        and one sequence synchronization worker to synchronize all sequences.
    ```
    
    Feels like this statement is not accurate and leaves an impression that a table has a fixed work to serve it. So I think we can enhance this statement a little bit as:
    
    ```
    Currently, only one table synchronization worker runs per table, and
    only one sequence synchronization worker runs per subscription at a time.
    ```
    
    2
    ```
    +<programlisting>
    +/* sub # */ CREATE SEQUENCE s1 START WITH 10 INCREMENT BY 1
    +/* sub # */ CREATE SEQUENCE s2 START WITH 100 INCREMENT BY 10;
    +</programlisting></para>
    ```
    
    Missed semi-colon for the first SQL statement.
    
    3
    ```
    +<programlisting>
    +/* sub # */ SELECT srrelid::regclass, srsublsn FROM pg_subscription_rel ;
    ```
    
    Unneeded white-space before the semi-colon.
    
    4
    ```
    +/* sub # */ SELECT * FROM s2
    + last_value | log_cnt | is_called
    +------------+---------+-----------
    +        610 |       0 | t
    +(1 row)
    ```
    
    Again, missed semi-colon.
    
    Best regards,
    --
    Chao Li (Evan)
    HighGo Software Co., Ltd.
    https://www.highgo.com/
    
    
    
    
    
    
    
    
  485. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-11-11T11:10:32Z

    On Tue, 11 Nov 2025 at 11:23, Chao Li <li.evan.chao@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > A few more comments:
    >
    > > On Nov 7, 2025, at 22:47, vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > The attached v20251107_2 version patch has the changes for the same.
    > >
    > > Regards,
    > > Vignesh
    > > <v20251107_2-0001-Documentation-for-sequence-synchronizati.patch>
    >
    > 1
    > ```
    > -        Currently, there can be only one synchronization worker per table.
    > +        Currently, there can be only one table synchronization worker per table
    > +        and one sequence synchronization worker to synchronize all sequences.
    > ```
    >
    > Feels like this statement is not accurate and leaves an impression that a table has a fixed work to serve it. So I think we can enhance this statement a little bit as:
    >
    > ```
    > Currently, only one table synchronization worker runs per table, and
    > only one sequence synchronization worker runs per subscription at a time.
    > ```
    
    Changed it slightly.
    
    > 2
    > ```
    > +<programlisting>
    > +/* sub # */ CREATE SEQUENCE s1 START WITH 10 INCREMENT BY 1
    > +/* sub # */ CREATE SEQUENCE s2 START WITH 100 INCREMENT BY 10;
    > +</programlisting></para>
    > ```
    >
    > Missed semi-colon for the first SQL statement.
    
    Modified
    
    > 3
    > ```
    > +<programlisting>
    > +/* sub # */ SELECT srrelid::regclass, srsublsn FROM pg_subscription_rel ;
    > ```
    >
    > Unneeded white-space before the semi-colon.
    
    Modified
    
    > 4
    > ```
    > +/* sub # */ SELECT * FROM s2
    > + last_value | log_cnt | is_called
    > +------------+---------+-----------
    > +        610 |       0 | t
    > +(1 row)
    > ```
    >
    > Again, missed semi-colon.
    
    Modified
    
    The attached v20251111 version patch has the changes for the same.
    
    Regards,
    Vignesh
    
  486. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2025-12-18T07:06:56Z

    On Tue, 11 Nov 2025 at 16:41, vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Tue, 11 Nov 2025 at 11:23, Chao Li <li.evan.chao@gmail.com> wrote:
    > >
    > > Hi Vignesh,
    > >
    > > A few more comments:
    > >
    > > > On Nov 7, 2025, at 22:47, vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > The attached v20251107_2 version patch has the changes for the same.
    > > >
    > > > Regards,
    > > > Vignesh
    > > > <v20251107_2-0001-Documentation-for-sequence-synchronizati.patch>
    > >
    > > 1
    > > ```
    > > -        Currently, there can be only one synchronization worker per table.
    > > +        Currently, there can be only one table synchronization worker per table
    > > +        and one sequence synchronization worker to synchronize all sequences.
    > > ```
    > >
    > > Feels like this statement is not accurate and leaves an impression that a table has a fixed work to serve it. So I think we can enhance this statement a little bit as:
    > >
    > > ```
    > > Currently, only one table synchronization worker runs per table, and
    > > only one sequence synchronization worker runs per subscription at a time.
    > > ```
    >
    > Changed it slightly.
    >
    > > 2
    > > ```
    > > +<programlisting>
    > > +/* sub # */ CREATE SEQUENCE s1 START WITH 10 INCREMENT BY 1
    > > +/* sub # */ CREATE SEQUENCE s2 START WITH 100 INCREMENT BY 10;
    > > +</programlisting></para>
    > > ```
    > >
    > > Missed semi-colon for the first SQL statement.
    >
    > Modified
    >
    > > 3
    > > ```
    > > +<programlisting>
    > > +/* sub # */ SELECT srrelid::regclass, srsublsn FROM pg_subscription_rel ;
    > > ```
    > >
    > > Unneeded white-space before the semi-colon.
    >
    > Modified
    >
    > > 4
    > > ```
    > > +/* sub # */ SELECT * FROM s2
    > > + last_value | log_cnt | is_called
    > > +------------+---------+-----------
    > > +        610 |       0 | t
    > > +(1 row)
    > > ```
    > >
    > > Again, missed semi-colon.
    >
    > Modified
    >
    > The attached v20251111 version patch has the changes for the same.
    
    Hi Team,
    
    While working on another thread, I noticed a bug introduced by commit
    as part of this thread.
    In function pg_get_publication_tables, We have code:
    ```
                         if (pub_elem->alltables)
            pub_elem_tables = GetAllPublicationRelations(RELKIND_RELATION,
                                   pub_elem->pubviaroot);
          else
          {
            List     *relids,
                   *schemarelids;
    
            relids = GetPublicationRelations(pub_elem->oid,
                             pub_elem->pubviaroot ?
                             PUBLICATION_PART_ROOT :
                             PUBLICATION_PART_LEAF);
            schemarelids = GetAllSchemaPublicationRelations(pub_elem->oid,
                                    pub_elem->pubviaroot ?
                                    PUBLICATION_PART_ROOT :
                                    PUBLICATION_PART_LEAF);
            pub_elem_tables = list_concat_unique_oid(relids, schemarelids);
          }
    ```
    
    So, when we create an 'ALL SEQUENCE publication' and we execute
    'SELECT * from pg_publication_tables'
    We will enter the else condition in the above code, which does not
    seem correct to me.
    It will call functions which are not required to be called. It will
    also call the function 'GetPublicationRelations' which contradicts the
    comment above this function.
    
    Similar issue is present for functions "InvalidatePubRelSyncCache" and
    "AlterPublicationOptions".
    
    Thanks,
    Shlok Kyal
    
  487. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-12-18T09:34:09Z

    On Thu, 18 Dec 2025 at 12:37, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    >
    > Hi Team,
    >
    > While working on another thread, I noticed a bug introduced by commit
    > as part of this thread.
    > In function pg_get_publication_tables, We have code:
    > ```
    >                      if (pub_elem->alltables)
    > pub_elem_tables = GetAllPublicationRelations(RELKIND_RELATION,
    >  pub_elem->pubviaroot);
    > else
    > {
    > List     *relids,
    >    *schemarelids;
    >
    > relids = GetPublicationRelations(pub_elem->oid,
    >  pub_elem->pubviaroot ?
    >  PUBLICATION_PART_ROOT :
    >  PUBLICATION_PART_LEAF);
    > schemarelids = GetAllSchemaPublicationRelations(pub_elem->oid,
    > pub_elem->pubviaroot ?
    > PUBLICATION_PART_ROOT :
    > PUBLICATION_PART_LEAF);
    > pub_elem_tables = list_concat_unique_oid(relids, schemarelids);
    > }
    > ```
    >
    > So, when we create an 'ALL SEQUENCE publication' and we execute
    > 'SELECT * from pg_publication_tables'
    > We will enter the else condition in the above code, which does not
    > seem correct to me.
    > It will call functions which are not required to be called. It will
    > also call the function 'GetPublicationRelations' which contradicts the
    > comment above this function.
    >
    > Similar issue is present for functions "InvalidatePubRelSyncCache" and
    > "AlterPublicationOptions".
    
    Thanks Shlok for reporting these issues,  In the areas highlighted, we
    can skip processing for sequences-only publications. The attached
    patch implements these changes.
    
    Regards,
    Vignesh
    
  488. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-12-18T11:33:20Z

    On Thu, Dec 18, 2025 at 3:04 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 18 Dec 2025 at 12:37, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    > >
    > > Hi Team,
    > >
    > > While working on another thread, I noticed a bug introduced by commit
    > > as part of this thread.
    > > In function pg_get_publication_tables, We have code:
    > > ```
    > >                      if (pub_elem->alltables)
    > > pub_elem_tables = GetAllPublicationRelations(RELKIND_RELATION,
    > >  pub_elem->pubviaroot);
    > > else
    > > {
    > > List     *relids,
    > >    *schemarelids;
    > >
    > > relids = GetPublicationRelations(pub_elem->oid,
    > >  pub_elem->pubviaroot ?
    > >  PUBLICATION_PART_ROOT :
    > >  PUBLICATION_PART_LEAF);
    > > schemarelids = GetAllSchemaPublicationRelations(pub_elem->oid,
    > > pub_elem->pubviaroot ?
    > > PUBLICATION_PART_ROOT :
    > > PUBLICATION_PART_LEAF);
    > > pub_elem_tables = list_concat_unique_oid(relids, schemarelids);
    > > }
    > > ```
    > >
    > > So, when we create an 'ALL SEQUENCE publication' and we execute
    > > 'SELECT * from pg_publication_tables'
    > > We will enter the else condition in the above code, which does not
    > > seem correct to me.
    > > It will call functions which are not required to be called. It will
    > > also call the function 'GetPublicationRelations' which contradicts the
    > > comment above this function.
    > >
    > > Similar issue is present for functions "InvalidatePubRelSyncCache" and
    > > "AlterPublicationOptions".
    >
    > Thanks Shlok for reporting these issues,  In the areas highlighted, we
    > can skip processing for sequences-only publications. The attached
    > patch implements these changes.
    >
    
    We have '!pub->alltables' check at 2 more places:
    -- pgoutput_row_filter_init()
    -- pg_get_publication_tables()
    
    Do we need to worry about '!allsequences' at these 2 places as well?
    
    thanks
    Shveta
    
    
    
    
  489. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-12-18T12:00:12Z

    On Thu, 18 Dec 2025 at 17:03, shveta malik <shveta.malik@gmail.com> wrote:
    >
    > On Thu, Dec 18, 2025 at 3:04 PM vignesh C <vignesh21@gmail.com> wrote:
    > >
    > > On Thu, 18 Dec 2025 at 12:37, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    > > >
    > > > Hi Team,
    > > >
    > > > While working on another thread, I noticed a bug introduced by commit
    > > > as part of this thread.
    > > > In function pg_get_publication_tables, We have code:
    > > > ```
    > > >                      if (pub_elem->alltables)
    > > > pub_elem_tables = GetAllPublicationRelations(RELKIND_RELATION,
    > > >  pub_elem->pubviaroot);
    > > > else
    > > > {
    > > > List     *relids,
    > > >    *schemarelids;
    > > >
    > > > relids = GetPublicationRelations(pub_elem->oid,
    > > >  pub_elem->pubviaroot ?
    > > >  PUBLICATION_PART_ROOT :
    > > >  PUBLICATION_PART_LEAF);
    > > > schemarelids = GetAllSchemaPublicationRelations(pub_elem->oid,
    > > > pub_elem->pubviaroot ?
    > > > PUBLICATION_PART_ROOT :
    > > > PUBLICATION_PART_LEAF);
    > > > pub_elem_tables = list_concat_unique_oid(relids, schemarelids);
    > > > }
    > > > ```
    > > >
    > > > So, when we create an 'ALL SEQUENCE publication' and we execute
    > > > 'SELECT * from pg_publication_tables'
    > > > We will enter the else condition in the above code, which does not
    > > > seem correct to me.
    > > > It will call functions which are not required to be called. It will
    > > > also call the function 'GetPublicationRelations' which contradicts the
    > > > comment above this function.
    > > >
    > > > Similar issue is present for functions "InvalidatePubRelSyncCache" and
    > > > "AlterPublicationOptions".
    > >
    > > Thanks Shlok for reporting these issues,  In the areas highlighted, we
    > > can skip processing for sequences-only publications. The attached
    > > patch implements these changes.
    > >
    >
    > We have '!pub->alltables' check at 2 more places:
    > -- pgoutput_row_filter_init()
    
    It's not necessary here, because only publications that actually
    replicate the given relation are passed to pgoutput_row_filter_init.
    Sequence publications are excluded from this list, so they will never
    appear there.
    
    > -- pg_get_publication_tables()
    
    We don't need to explicitly check !pub->allsequences here. The guard
    if (funcctx->call_cntr < list_length(table_infos))
    already ensures that the remaining code is executed only when
    table_infos contains elements. If the list has entries, it necessarily
    represents a table publication, and it will enumerate those tables. If
    the list is empty, the condition fails and no rows are returned, so
    the extra check is not required.
    
    Regards,
    Vignesh
    
    
    
    
  490. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-12-19T04:34:53Z

    On Thu, Dec 18, 2025 at 5:30 PM vignesh C <vignesh21@gmail.com> wrote:
    >
    > On Thu, 18 Dec 2025 at 17:03, shveta malik <shveta.malik@gmail.com> wrote:
    > >
    > > On Thu, Dec 18, 2025 at 3:04 PM vignesh C <vignesh21@gmail.com> wrote:
    > > >
    > > > On Thu, 18 Dec 2025 at 12:37, Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    > > > >
    > > > > Hi Team,
    > > > >
    > > > > While working on another thread, I noticed a bug introduced by commit
    > > > > as part of this thread.
    > > > > In function pg_get_publication_tables, We have code:
    > > > > ```
    > > > >                      if (pub_elem->alltables)
    > > > > pub_elem_tables = GetAllPublicationRelations(RELKIND_RELATION,
    > > > >  pub_elem->pubviaroot);
    > > > > else
    > > > > {
    > > > > List     *relids,
    > > > >    *schemarelids;
    > > > >
    > > > > relids = GetPublicationRelations(pub_elem->oid,
    > > > >  pub_elem->pubviaroot ?
    > > > >  PUBLICATION_PART_ROOT :
    > > > >  PUBLICATION_PART_LEAF);
    > > > > schemarelids = GetAllSchemaPublicationRelations(pub_elem->oid,
    > > > > pub_elem->pubviaroot ?
    > > > > PUBLICATION_PART_ROOT :
    > > > > PUBLICATION_PART_LEAF);
    > > > > pub_elem_tables = list_concat_unique_oid(relids, schemarelids);
    > > > > }
    > > > > ```
    > > > >
    > > > > So, when we create an 'ALL SEQUENCE publication' and we execute
    > > > > 'SELECT * from pg_publication_tables'
    > > > > We will enter the else condition in the above code, which does not
    > > > > seem correct to me.
    > > > > It will call functions which are not required to be called. It will
    > > > > also call the function 'GetPublicationRelations' which contradicts the
    > > > > comment above this function.
    > > > >
    > > > > Similar issue is present for functions "InvalidatePubRelSyncCache" and
    > > > > "AlterPublicationOptions".
    > > >
    > > > Thanks Shlok for reporting these issues,  In the areas highlighted, we
    > > > can skip processing for sequences-only publications. The attached
    > > > patch implements these changes.
    > > >
    > >
    > > We have '!pub->alltables' check at 2 more places:
    > > -- pgoutput_row_filter_init()
    >
    > It's not necessary here, because only publications that actually
    > replicate the given relation are passed to pgoutput_row_filter_init.
    > Sequence publications are excluded from this list, so they will never
    > appear there.
    >
    > > -- pg_get_publication_tables()
    >
    > We don't need to explicitly check !pub->allsequences here. The guard
    > if (funcctx->call_cntr < list_length(table_infos))
    > already ensures that the remaining code is executed only when
    > table_infos contains elements. If the list has entries, it necessarily
    > represents a table publication, and it will enumerate those tables. If
    > the list is empty, the condition fails and no rows are returned, so
    > the extra check is not required.
    >
    
    Okay, the patch LGTM.
    
    thanks
    Shveta
    
    
    
    
  491. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-12-19T04:35:30Z

    Hi Vignesh.
    
    I had a quick look at this patch.
    
    ======
    
    - * Instead, we invalidate only the relsyncache.
    + * Instead, invalidate the relation sync cache for publications that
    + * include tables. Invalidation is not required for sequences only
    + * publications.
      */
    - InvalidatePubRelSyncCache(pub->oid, pub->puballtables);
    + if (!pub->puballsequences || pub->puballtables)
    + InvalidatePubRelSyncCache(pub->oid, pub->puballtables);
    
    I felt all these "sequence only" conditions are becoming difficult to read.
    
    It wonder if it would be better to introduce some function like:
    
    bool
    PubHasSequencesOnly(pub)
    {
      return pub->puballsequences && !pub->puballtables;
    }
    
    IIUC the current patch code only works because publication syntax like
    below is not yet supported:
    
    CREATE PUBLICATION pub1 FOR ALL SEQUENCES, TABLE t1;
    
    But when that syntax does become possible, then all these conditions
    will be broken.
    
    Should we prepare for that eventuality by introducing some function
    right now, so as to contain all the future broken code?
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  492. Re: Logical Replication of sequences

    vignesh C <vignesh21@gmail.com> — 2025-12-19T11:35:27Z

    On Fri, 19 Dec 2025 at 10:05, Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh.
    >
    > I had a quick look at this patch.
    >
    > ======
    >
    > - * Instead, we invalidate only the relsyncache.
    > + * Instead, invalidate the relation sync cache for publications that
    > + * include tables. Invalidation is not required for sequences only
    > + * publications.
    >   */
    > - InvalidatePubRelSyncCache(pub->oid, pub->puballtables);
    > + if (!pub->puballsequences || pub->puballtables)
    > + InvalidatePubRelSyncCache(pub->oid, pub->puballtables);
    >
    > I felt all these "sequence only" conditions are becoming difficult to read.
    >
    > It wonder if it would be better to introduce some function like:
    >
    > bool
    > PubHasSequencesOnly(pub)
    > {
    >   return pub->puballsequences && !pub->puballtables;
    > }
    
    I added a macro following a similar pattern. However, since the
    function calls use different data types, I modified it to pass
    individual members instead of the structure.
    
    > IIUC the current patch code only works because publication syntax like
    > below is not yet supported:
    >
    > CREATE PUBLICATION pub1 FOR ALL SEQUENCES, TABLE t1;
    >
    > But when that syntax does become possible, then all these conditions
    > will be broken.
    >
    > Should we prepare for that eventuality by introducing some function
    > right now, so as to contain all the future broken code?
    
    I believe no specific handling is required. These flows will be
    naturally addressed as part of the feature implementation.
    
    The attached patch has the changes for the comments.
    
    Regards,
    Vignesh
    
  493. Re: Logical Replication of sequences

    Peter Smith <smithpb2250@gmail.com> — 2025-12-21T23:10:51Z

    Hi Vignesh,
    
    A couple of review comments for v2-0001
    
    ======
    src/backend/catalog/pg_publication.c
    
    pg_get_publication_tables:
    
    1.
      if (pub_elem->alltables)
      pub_elem_tables = GetAllPublicationRelations(RELKIND_RELATION,
      pub_elem->pubviaroot);
    - else
    + else if (!pub_elem->allsequences)
      {
      List    *relids,
         *schemarelids;
    @@ -1203,8 +1203,13 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
      table_infos = lappend(table_infos, table_info);
      }
    
    - /* At least one publication is using publish_via_partition_root. */
    - if (pub_elem->pubviaroot)
    + /*
    + * At least one publication is using publish_via_partition_root.
    + * Skip sequences only publications, as publish_via_partition_root
    + * is applicable only to table publications.
    + */
    + if (pub_elem->pubviaroot && !PUB_HAS_SEQUENCES_ONLY(pub_elem->allsequences,
    + pub_elem->alltables))
      viaroot = true;
    
    Won't it be simpler to check this up-front and then just 'continue'?
    Then you wouldn't have to handle "sequence only" for the rest of the
    loop logic.
    
    e.g.
    
    pub_elem = ...
    
    /* Skip this publication if no TABLES are published. */
    if (PUB_HAS_SEQUENCES_ONLY(pub_elem->allsequences, pub_elem->alltables)
      continue;
    
    if (pub_elem->alltables)
      ...
    else
      ...
    
    ======
    src/backend/commands/publicationcmds.c
    
    2.
    - if (!pubform->puballtables && publish_via_partition_root_given &&
    - !publish_via_partition_root)
    + if (!pubform->puballtables && !pubform->puballsequences &&
    + publish_via_partition_root_given && !publish_via_partition_root)
    
    I felt this modified condition ought to be expressed as:
    
    if (!PUB_HAS_SEQUENCES_ONLY(...) && <original condition>
    
    ======
    Kind Regards,
    Peter Smith.
    Fujitsu Australia
    
    
    
    
  494. Re: Logical Replication of sequences

    shveta malik <shveta.malik@gmail.com> — 2025-12-22T04:50:30Z

    On Mon, Dec 22, 2025 at 4:41 AM Peter Smith <smithpb2250@gmail.com> wrote:
    >
    > Hi Vignesh,
    >
    > A couple of review comments for v2-0001
    >
    > ======
    > src/backend/catalog/pg_publication.c
    >
    > pg_get_publication_tables:
    >
    > 1.
    >   if (pub_elem->alltables)
    >   pub_elem_tables = GetAllPublicationRelations(RELKIND_RELATION,
    >   pub_elem->pubviaroot);
    > - else
    > + else if (!pub_elem->allsequences)
    >   {
    >   List    *relids,
    >      *schemarelids;
    > @@ -1203,8 +1203,13 @@ pg_get_publication_tables(PG_FUNCTION_ARGS)
    >   table_infos = lappend(table_infos, table_info);
    >   }
    >
    > - /* At least one publication is using publish_via_partition_root. */
    > - if (pub_elem->pubviaroot)
    > + /*
    > + * At least one publication is using publish_via_partition_root.
    > + * Skip sequences only publications, as publish_via_partition_root
    > + * is applicable only to table publications.
    > + */
    > + if (pub_elem->pubviaroot && !PUB_HAS_SEQUENCES_ONLY(pub_elem->allsequences,
    > + pub_elem->alltables))
    >   viaroot = true;
    >
    > Won't it be simpler to check this up-front and then just 'continue'?
    > Then you wouldn't have to handle "sequence only" for the rest of the
    > loop logic.
    
    +1. It will simplify the code.
    
    > e.g.
    >
    > pub_elem = ...
    >
    > /* Skip this publication if no TABLES are published. */
    > if (PUB_HAS_SEQUENCES_ONLY(pub_elem->allsequences, pub_elem->alltables)
    >   continue;
    >
    > if (pub_elem->alltables)
    >   ...
    > else
    >   ...
    >
    > ======
    > src/backend/commands/publicationcmds.c
    >
    > 2.
    > - if (!pubform->puballtables && publish_via_partition_root_given &&
    > - !publish_via_partition_root)
    > + if (!pubform->puballtables && !pubform->puballsequences &&
    > + publish_via_partition_root_given && !publish_via_partition_root)
    >
    > I felt this modified condition ought to be expressed as:
    >
    > if (!PUB_HAS_SEQUENCES_ONLY(...) && <original condition>
    >
    > ======
    > Kind Regards,
    > Peter Smith.
    > Fujitsu Australia
    
    
    
    
  495. Re: Logical Replication of sequences

    Amit Kapila <amit.kapila16@gmail.com> — 2025-12-22T05:38:39Z

    On Thu, Dec 18, 2025 at 12:37 PM Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    >
    > While working on another thread, I noticed a bug introduced by commit
    > as part of this thread.
    > In function pg_get_publication_tables, We have code:
    > ```
    >                      if (pub_elem->alltables)
    > pub_elem_tables = GetAllPublicationRelations(RELKIND_RELATION,
    >  pub_elem->pubviaroot);
    > else
    > {
    > List     *relids,
    >    *schemarelids;
    >
    > relids = GetPublicationRelations(pub_elem->oid,
    >  pub_elem->pubviaroot ?
    >  PUBLICATION_PART_ROOT :
    >  PUBLICATION_PART_LEAF);
    > schemarelids = GetAllSchemaPublicationRelations(pub_elem->oid,
    > pub_elem->pubviaroot ?
    > PUBLICATION_PART_ROOT :
    > PUBLICATION_PART_LEAF);
    > pub_elem_tables = list_concat_unique_oid(relids, schemarelids);
    > }
    > ```
    >
    > So, when we create an 'ALL SEQUENCE publication' and we execute
    > 'SELECT * from pg_publication_tables'
    > We will enter the else condition in the above code, which does not
    > seem correct to me.
    > It will call functions which are not required to be called. It will
    > also call the function 'GetPublicationRelations' which contradicts the
    > comment above this function.
    >
    
    I see that we will needlessly call GetPublicationRelations or others
    for all_schema publication but is there any problem/bug due to that?
    AFAICS, the function will still return correct results. Yes, there is
    an argument to better performance for large numbers of all_sequence
    publications and that too in DDL like Create/Alter Subscription. I am
    not sure that it is really worth adding more checks at multiple places
    in the code though we can improve comments atop
    GetPublicationRelations. I feel if we encounter such cases in the
    field then it makes sense to add these additional optimizations at
    various places.
    
    -- 
    With Regards,
    Amit Kapila.
    
    
    
    
  496. Re: Logical Replication of sequences

    Shlok Kyal <shlok.kyal.oss@gmail.com> — 2025-12-24T06:45:19Z

    On Mon, 22 Dec 2025 at 11:08, Amit Kapila <amit.kapila16@gmail.com> wrote:
    >
    > On Thu, Dec 18, 2025 at 12:37 PM Shlok Kyal <shlok.kyal.oss@gmail.com> wrote:
    > >
    > > While working on another thread, I noticed a bug introduced by commit
    > > as part of this thread.
    > > In function pg_get_publication_tables, We have code:
    > > ```
    > >                      if (pub_elem->alltables)
    > > pub_elem_tables = GetAllPublicationRelations(RELKIND_RELATION,
    > >  pub_elem->pubviaroot);
    > > else
    > > {
    > > List     *relids,
    > >    *schemarelids;
    > >
    > > relids = GetPublicationRelations(pub_elem->oid,
    > >  pub_elem->pubviaroot ?
    > >  PUBLICATION_PART_ROOT :
    > >  PUBLICATION_PART_LEAF);
    > > schemarelids = GetAllSchemaPublicationRelations(pub_elem->oid,
    > > pub_elem->pubviaroot ?
    > > PUBLICATION_PART_ROOT :
    > > PUBLICATION_PART_LEAF);
    > > pub_elem_tables = list_concat_unique_oid(relids, schemarelids);
    > > }
    > > ```
    > >
    > > So, when we create an 'ALL SEQUENCE publication' and we execute
    > > 'SELECT * from pg_publication_tables'
    > > We will enter the else condition in the above code, which does not
    > > seem correct to me.
    > > It will call functions which are not required to be called. It will
    > > also call the function 'GetPublicationRelations' which contradicts the
    > > comment above this function.
    > >
    >
    > I see that we will needlessly call GetPublicationRelations or others
    > for all_schema publication but is there any problem/bug due to that?
    No, I did not encounter a problem/bug.
    
    > AFAICS, the function will still return correct results. Yes, there is
    > an argument to better performance for large numbers of all_sequence
    > publications and that too in DDL like Create/Alter Subscription. I am
    > not sure that it is really worth adding more checks at multiple places
    > in the code though we can improve comments atop
    > GetPublicationRelations. I feel if we encounter such cases in the
    > field then it makes sense to add these additional optimizations at
    > various places.
    >
    I agree with you. And attached a patch to modify the comment above
    GetPublicationRelations.
    
    Thanks,
    Shlok Kyal