Skip to content

[3.0] Sync PostgreSQL sequences with the rows the installer inserts - #9348

Open
albertlast wants to merge 1 commit into
SimpleMachines:release-3.0from
albertlast:fix/pg-install-sequences
Open

[3.0] Sync PostgreSQL sequences with the rows the installer inserts#9348
albertlast wants to merge 1 commit into
SimpleMachines:release-3.0from
albertlast:fix/pg-install-sequences

Conversation

@albertlast

Copy link
Copy Markdown
Collaborator

Description

On a freshly installed PostgreSQL forum, the first topic anybody starts is silently not created.

The table schemas carry initial data with explicit IDs — the default board is board 1, and other seeded rows refer to each other by number — so those values are supplied to the INSERT rather than generated. MySQL notices a value above its AUTO_INCREMENT counter and moves the counter along by itself. PostgreSQL does not: a sequence only advances when something calls nextval() on it, nothing has, so it still sits at 1 and hands 1 to the next insert. That collides with the row already there:

ERROR:  duplicate key value violates unique constraint "smf_topics_pkey"
ERROR:  duplicate key value violates unique constraint "smf_messages_pkey"

28 sequences are in that state on a new install — boards, categories, membergroups, smileys, attachments, polls, personal_messages, scheduled_tasks and more.

What makes it easy to miss rather than easy to report:

  • It does not look like a database problem. Post2 runs on to its normal redirect, the browser lands on the board, and the topic simply is not there. Nothing is shown to the user and nothing reaches log_errors.
  • It fixes itself after one attempt. The insert that failed still consumed the 1, so the retry gets 2 and succeeds. Anyone who tries again concludes it was a fluke, and the forum behaves correctly from then on.

Because of that second point it only reproduces on a forum that has just been installed, which is why it has survived this long.

The fix

Table::populate() already works out which column auto-increments, in order to decide its insert mode. After the insert it now points the generator past what it just wrote. On MySQL this returns immediately.

This is not a new idea in the codebase: the 2.1 upgrade path has carried the same setval() for years, as Sources/Maintenance/Migration/v2_1/PostgreSqlSequences.php. Installs never got the equivalent.

Testing

The unit suite cannot reach this — it needs a database, and the state only exists on a forum that has just been installed.

Verified by hand on both engines, installing from scratch each time:

  • PostgreSQL, before: starting the first topic returns 302 to the board and creates nothing; the PostgreSQL log shows the duplicate key errors above; pg_sequences.last_value is NULL for 28 sequences.
  • PostgreSQL, after: no seeded table's sequence is left uncalled, and the first topic and its first reply post normally.
  • MySQL: reinstalled and exercised as well, since populate() is shared. Unchanged, as expected.

Issues References (Fixes|Related|Closes)

Found while running HTTP tests against a freshly installed forum in #9347. Not otherwise reported that I can find.

A table's initial data carries its own IDs - the default board is board 1,
and other rows in it refer to each other by number - so those values are
supplied to the INSERT rather than generated.

MySQL sees a value larger than its AUTO_INCREMENT counter and moves the
counter along by itself. PostgreSQL does not: a sequence only advances
when something calls nextval() on it, nothing has, so it still sits at 1
and hands 1 to the next insert. That collides with the row already there
and the insert fails on the primary key.

On a new PostgreSQL forum, 28 sequences are in that state. Starting the
first topic is the usual way to meet it, and the symptom is not obviously
a database problem: Post2 runs on to its normal redirect, the browser
lands on the board, and no topic is there. It then works on the second
try, because the attempt that failed still consumed the 1 and the retry
gets 2 - which makes it look like a fluke rather than something to
report.

The 2.1 upgrade path has carried this fix for years, as the
PostgreSqlSequences migration. This is the same setval() for a fresh
install, next to the insert that causes it, and it is a no-op on MySQL.

Not covered by the unit suite: it needs a database, and it only shows up
on a forum that has just been installed. Verified by installing on
PostgreSQL and posting - the first topic now works where it previously
vanished - and by checking that the sequences report a position instead
of never having been called. MySQL was reinstalled and exercised too,
since populate() is shared.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: albertlast <mathiaspapealbert@hotmail.com>
@sbulen

sbulen commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

My recommendation is to cut over to Identity Columns in 3.0.

https://www.simplemachines.org/community/index.php?topic=592387.0

@albertlast

Copy link
Copy Markdown
Collaborator Author

i know, but this is here a bug fix pr, not feature pr ^^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants