Skip to content

[3.0] Keeps a backup table from depending on the live table's sequence - #9650

Closed
albertlast wants to merge 1 commit into
SimpleMachines:release-3.0from
albertlast:3.0/pg-backup-sequence-dependency
Closed

[3.0] Keeps a backup table from depending on the live table's sequence#9650
albertlast wants to merge 1 commit into
SimpleMachines:release-3.0from
albertlast:3.0/pg-backup-sequence-dependency

Conversation

@albertlast

@albertlast albertlast commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Description

On PostgreSQL, an upgrade that was asked to back up the database cannot finish. It gets as far as the migration that folds holidays into events and stops there:

 +++ Migrating holidays to events... ERROR:  cannot drop sequence smf_calendar_holidays_seq because other objects depend on it
DETAIL:  default value for column id_holiday of table backup_smf_calendar_holidays depends on sequence smf_calendar_holidays_seq
HINT:  Use DROP ... CASCADE to drop the dependent objects too.

backup_table() copies a table with CREATE TABLE backup_x (LIKE x INCLUDING DEFAULTS).

A sequence in PostgreSQL is an object in its own right, related to the column it feeds but not carried along by a copy of that column. INCLUDING DEFAULTS copies a default as the expression it is written with, so backup_smf_calendar_holidays.id_holiday is given the default nextval('smf_calendar_holidays_seq'), pointing at the sequence behind the live table rather than at one of its own.

Two things follow. The backup becomes an object that sequence cannot be dropped without, which is what HolidaysToEvents is trying to do; and anything inserted into a backup table would draw its id from the live table's counter.

The copy is still made INCLUDING DEFAULTS, and only the defaults that name a sequence are taken off afterwards, a column at a time. Every other default is left alone: a default is part of what a column is, and a backup that has lost them is a poorer thing to rebuild from than one that has kept them.

What the backup still does not carry is unchanged by this. LIKE without INCLUDING INDEXES or INCLUDING CONSTRAINTS has never copied indexes, primary keys or constraints, and the @todo above the statement, asking whether sequences should be backed up as well, is left as it was. Giving each backup a sequence of its own is a larger question than an upgrade that cannot finish.

How this was verified

Upgrading the 2.1.7 baseline from the 2.1 development environment with the backup step turned on. Reaching this at all needs #9649, which fixes an earlier failure in the same step; both were applied together.

before after
PostgreSQL, backups on stops at "Migrating holidays to events" Upgrade complete!
MySQL, backups on runs to completion runs to completion

Then reading the catalogue on the upgraded database, to confirm the change takes what it means to and nothing else:

sequence defaults on live tables 41
sequence defaults left on backup_ tables 0
ordinary defaults on backup_ tables, matching the live table column for column 418

The eleven live defaults with no match on a backup table are all accounted for by the backup being a copy of an earlier moment: smf_mail_queue.next_try and tries have no column on the backup at all because a migration added them after the copy was taken, and smf_pm_recipients.in_inbox reads '1'::smallint against a live 1 because the live column's type changed. None of them is a default this removes.

Also with the upgrade killed part way and started again, with backups on. It recovered in one run, and every non-backup_ object matched an uninterrupted upgrade: 323 tables, sequences, indexes, constraints, functions, aggregates and operators, 65 row counts, 228 settings, and the position of all 38 sequences.

MySQL is unaffected throughout: it copies with CREATE TABLE backup_x LIKE x, and an AUTO_INCREMENT counter belongs to its table rather than being a separate object, so a backup cannot hold the original's.

Not reachable from the unit suite

backup_table() is a database driver method and needs a connection.

Issues References (Fixes|Related|Closes)

  1. Related: [3.0] Returns a bool from the substep that backs up a table #9649, which has to be in place before this one can be reached.

LIKE ... INCLUDING DEFAULTS copies a default as the expression it is
written with, so backup_smf_calendar_holidays.id_holiday defaulted to
nextval on smf_calendar_holidays_seq. That makes the backup an object
the sequence cannot be dropped without, and HolidaysToEvents drops it.

Only the defaults that name a sequence are taken off, once the copy
has been made. The others say what a column holds when nothing supplies
it, which is part of what makes the backup worth restoring from.

Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
@albertlast
albertlast marked this pull request as draft September 6, 2026 09:57
@albertlast
albertlast force-pushed the 3.0/pg-backup-sequence-dependency branch from 21b4148 to eeb76dc Compare September 6, 2026 09:57
@albertlast

Copy link
Copy Markdown
Collaborator Author

Closing this in favour of a different approach.

Both shapes I tried here argue about defaults, which is the wrong axis. The backup is at once incomplete and over-coupled: LIKE never copied indexes, primary keys or constraints, while INCLUDING DEFAULTS borrowed the live table's sequence.

Splitting the two — the backup_ table holding rows, a stored definition holding the shape — makes the sequence dependency not arise at all, and makes a backup restorable rather than merely non-blocking. That work will be its own pull request.

#9649 is unaffected and still needed: without it a PostgreSQL upgrade with backups on stops at the first table.

@albertlast albertlast closed this Sep 6, 2026
@jdarwood007 jdarwood007 added this to the 3.0 Alpha 5 milestone Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants