Skip to content

Update to MusicBrainz schema 31 (rebase of #26) - #27

Merged
lalinsky merged 9 commits into
mainfrom
schema-v31-update
Jul 26, 2026
Merged

lalinsky merged 9 commits into
mainfrom
schema-v31-update

Conversation

@lalinsky

Copy link
Copy Markdown
Member

Rebases #26 (by @frisi, branch MD-131-schema-update-v31 on molindo/mbslave) on top of current main (post-#24) and resolves the resulting conflicts:

No other conflicts. py_compile passes on all Python files.

Closes #26.

Harald Friessnegger and others added 7 commits May 26, 2025 14:06
note that this reverts the adaptions done by #8

as musicbrainz does not ship the scripts with function definitions
containing a `SET schema` local adaptions would always lead to merge
problems.

if users have problems that functions do not use the correct schema for
queries and can't find functions or tables, consider to set the schema on session,
user or database level:

```
-- session
SET search_path to musicbrainz,public;

-- user level
ALTER USER musicbrainz SET search_path TO musicbrainz, public;

-- check user level settings via psql
\drds mbdata;

-- check user level via query
SELECT
    r.rolname AS role_name,
    rs.setconfig AS configured_settings
FROM
    pg_roles r
LEFT JOIN
    pg_db_role_setting rs ON r.oid = rs.setrole
WHERE
    r.rolname = 'musicbrainz';

-- db level
SELECT setting FROM pg_settings WHERE name = 'search_path';
ALTER DATABASE database_name SET search_path TO musicbrainz, public;
```
musicbrainz has fixed upgrade issues
see metabrainz/musicbrainz-server@c7b8c29
# Conflicts:
#	CHANGELOG.rst
#	mbslave/__init__.py
#	mbslave/sql/CreateFunctions.sql
@coderabbitai

coderabbitai Bot commented Jul 26, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@lalinsky, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 14 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4e8f6478-8025-4bca-b7b8-4fe09ee5357b

📥 Commits

Reviewing files that changed from the base of the PR and between 5f4471e and 75c118b.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • mbslave/replication.py
  • pyproject.toml

Walkthrough

Changes

Schema 31 and replication

Layer / File(s) Summary
Release metadata and setup wiring
CHANGELOG.rst, README.rst, mbslave/__init__.py, mbslave/replication.py, mbslave/sql/dbmirror2/README, mbslave/sql/*ReplicationTriggers2.sql
Version 31 metadata, upgrade instructions, dbmirror2 references, and aggregate trigger helpers are updated.
Schema entities and data migrations
mbslave/sql/CreateConstraints.sql, mbslave/sql/CreateTables.sql, mbslave/sql/CreateViews.sql, mbslave/sql/updates/*, mbslave/sql/updates/schema-change/31.all.sql, mbslave/sql/updates/schema-change/31.master_and_standalone.sql
Series relationships, constraints, identifier-column removal, release-label cleanup, and schema-change 31 definitions are added.
dbmirror2 queued change capture
mbslave/sql/dbmirror2/dbmirror2.sql, mbslave/sql/updates/20260502-search-756-*, mbslave/sql/updates/20260507-search-756-*, mbslave/sql/updates/schema-change/31.*_only.sql, mbslave/sql/*Triggers*.sql
Row changes are stored as JSON in pending tables, cascade ordering is corrected, and installation and cleanup scripts cover the new capture objects.
Editor-data sanitization
mbslave/sql/CreateFunctions.sql, mbslave/sql/CreateCustomReplicationTriggers2.sql, mbslave/sql/CreateViews.sql, mbslave/sql/updates/20260502-search-756-all.sql, mbslave/sql/updates/schema-change/31.all.sql, mbslave/sql/updates/schema-change/31.master_only.sql
Editor rows and mirrored editor payloads are sanitized through functions, a conditional trigger, and the editor_sanitized view.

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly names the schema v31 update and rebase of #26, which matches the main change.
Description check ✅ Passed The description is directly about the schema v31 rebase and conflict resolution, so it matches the change set.
Linked Issues check ✅ Passed The PR updates mbslave for MusicBrainz schema v31 and includes the requested schema-change work from #26.
Out of Scope Changes check ✅ Passed The added SQL, docs, and version bumps all support the schema v31 update; no unrelated changes stand out.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch schema-v31-update

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mbslave/sql/updates/20260121-mbs-14092.sql`:
- Around line 79-81: Update the series_type seed INSERT for IDs 16 and 17 to use
the file’s established ON CONFLICT DO NOTHING pattern, preserving both rows’
values. Also update the migration’s SetSequences handling so the series_type ID
sequence is advanced beyond 17 and later inserts cannot collide.
- Around line 15-27: Update the series_series view’s link_type gid filter to use
the series→series part-of gid 8fe04b66-fe39-40ce-a28f-76b816d3f55a in
mbslave/sql/updates/20260121-mbs-14092.sql lines 15-27,
mbslave/sql/CreateViews.sql lines 86-98, and
mbslave/sql/updates/schema-change/31.all.sql lines 24-36; make the same
replacement in each view definition.

In `@mbslave/sql/updates/20260502-search-756-master_only.sql`:
- Around line 22-28: The pdcursor parameter in every recordchange() copy must
use BIGINT to match the BIGINT oooseqid and pending_data.seqid types. Update
mbslave/sql/updates/20260502-search-756-master_only.sql:22-28,
mbslave/sql/updates/20260507-search-756-mirror_only.sql:22-28, and
mbslave/sql/updates/20260507-search-756-standalone_only.sql:25-31; then
regenerate mbslave/sql/updates/schema-change/31.master_only.sql:28-34 and
mbslave/sql/updates/schema-change/31.mirror_only.sql:28-34 from the corrected
source.

In `@mbslave/sql/updates/schema-change/31.standalone_only.sql`:
- Around line 29-37: Change the pdcursor parameter type from INTEGER to BIGINT
in the standalone schema-change SQL and the corresponding dbmirror2 SQL
definition, while leaving the oooseqid declaration and cursor query behavior
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7e200039-0697-404c-933b-c1feb8a18eb7

📥 Commits

Reviewing files that changed from the base of the PR and between 5753448 and 5f4471e.

📒 Files selected for processing (36)
  • CHANGELOG.rst
  • README.rst
  • mbslave/__init__.py
  • mbslave/replication.py
  • mbslave/sql/CreateAllReplicationTriggers2.sql
  • mbslave/sql/CreateConstraints.sql
  • mbslave/sql/CreateCustomReplicationTriggers2.sql
  • mbslave/sql/CreateFunctions.sql
  • mbslave/sql/CreateReplicationTriggers2.sql
  • mbslave/sql/CreateTables.sql
  • mbslave/sql/CreateViews.sql
  • mbslave/sql/DropAllReplicationTriggers2.sql
  • mbslave/sql/DropCustomReplicationTriggers2.sql
  • mbslave/sql/DropFunctions.sql
  • mbslave/sql/DropMirrorOnlyTriggers.sql
  • mbslave/sql/DropReplicationTriggers2.sql
  • mbslave/sql/DropTriggers.sql
  • mbslave/sql/DropViews.sql
  • mbslave/sql/dbmirror2/README
  • mbslave/sql/dbmirror2/RefreshColumnInfo.sql
  • mbslave/sql/dbmirror2/ReplicationSetup.sql
  • mbslave/sql/dbmirror2/dbmirror2.sql
  • mbslave/sql/updates/20260121-mbs-14092-fks.sql
  • mbslave/sql/updates/20260121-mbs-14092.sql
  • mbslave/sql/updates/20260212-mbs-14252.sql
  • mbslave/sql/updates/20260422-mbs-6551-all.sql
  • mbslave/sql/updates/20260422-mbs-6551-master_and_standalone.sql
  • mbslave/sql/updates/20260502-search-756-all.sql
  • mbslave/sql/updates/20260502-search-756-master_only.sql
  • mbslave/sql/updates/20260507-search-756-mirror_only.sql
  • mbslave/sql/updates/20260507-search-756-standalone_only.sql
  • mbslave/sql/updates/schema-change/31.all.sql
  • mbslave/sql/updates/schema-change/31.master_and_standalone.sql
  • mbslave/sql/updates/schema-change/31.master_only.sql
  • mbslave/sql/updates/schema-change/31.mirror_only.sql
  • mbslave/sql/updates/schema-change/31.standalone_only.sql
💤 Files with no reviewable changes (2)
  • mbslave/sql/dbmirror2/RefreshColumnInfo.sql
  • mbslave/sql/dbmirror2/ReplicationSetup.sql

Comment on lines +15 to +27
CREATE OR REPLACE VIEW series_series AS
SELECT entity0 AS series_part,
entity1 AS series,
lss.id AS relationship,
link_order,
lss.link,
COALESCE(text_value, '') AS text_value
FROM l_series_series lss
JOIN series s ON s.id = lss.entity1
JOIN link l ON l.id = lss.link
JOIN link_type lt ON (lt.id = l.link_type AND lt.gid = '8da75c99-46ff-373c-9d31-276ca8fa8cc3')
LEFT OUTER JOIN link_attribute_text_value latv ON (latv.attribute_type = 788 AND latv.link = l.id)
ORDER BY series, link_order;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
fd -a '^(20260121-mbs-14092|CreateViews|31\.all|31\.master_only|31\.mirror_only|.*search-756.*)\.sql$' . | sed 's#^\./##' | sort

echo
echo "== search gid occurrences =="
rg -n "8da75c99|8fe04b66|SERIES_PART_OF_SERIES_GID|series_series|part of|Link:.*series" . -g '*.sql' -g '*.json' || true

echo
echo "== inspect candidate files around views and seed/DDL references =="
for f in \
  mbslave/sql/updates/20260121-mbs-14092.sql \
  mbslave/sql/CreateViews.sql \
  mbslave/sql/updates/schema-change/31.all.sql
do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    cat -n "$f"
  fi
done

echo
echo "== list scripts mentioning 1307 link_type and series =="
rg -n "1307|series|series_series|link_type" mbslave/sql -g '*.sql' | head -n 200

Repository: acoustid/mbslave

Length of output: 50372


🌐 Web query:

MusicBrainz link_type gid '8fe04b66-fe39-40ce-a28f-76b816d3f55a' series series part of

💡 Result:

The MusicBrainz link_type GID 8fe04b66-fe39-40ce-a28f-76b816d3f55a is not identified in the provided search results as a recognized relationship type in the MusicBrainz database. MusicBrainz uses GIDs (globally unique identifiers) to uniquely identify relationship types [1][2], and these types are documented in specific relationship type pages, such as those for Series-Series, Release-Series, and Release group-Series relationships [3][4][5]. While these documented relationship types cover various ways entities are linked—including "part of" relationships for releases and release groups [4][5]—the specific GID provided does not appear in the available documentation or search results.

Citations:


🌐 Web query:

MusicBrainz link_type gid '8da75c99-46ff-373c-9d31-276ca8fa8cc3'

💡 Result:

In the MusicBrainz database, the Global Identifier (GID) '8da75c99-46ff-373c-9d31-276ca8fa8cc3' corresponds to a link type related to the 'series' entity [1]. Specifically, it is defined in the MusicBrainz codebase as the link type for the 'series' entity itself within the context of 'part of series' relationships [1]. This GID is used to identify this specific relationship type within the link_type table of the MusicBrainz database schema [2][1].

Citations:


🌐 Web query:

MusicBrainz Server SeriesPartOf SeriesGID 8fe04b66-fe39-40ce-a28f-76b816d3f55a

💡 Result:

The identifier 8fe04b66-fe39-40ce-a28f-76b816d3f55a is a MusicBrainz GUID (Globally Unique Identifier), also known as an MBID, which specifically identifies a Series entity within the MusicBrainz database [1][2]. In the MusicBrainz data model, a Series represents a sequence of related entities—such as release groups, releases, recordings, works, artists, or events—that share a common theme or branding [2]. Each series is assigned a unique MBID (the GUID) to distinguish it from other entities in the system [1]. While your query references SeriesPartOf and SeriesGID, please note the following technical details regarding MusicBrainz terminology: - SeriesGID: This is a common way to refer to the Global Unique Identifier (GID) of a Series entity [1][3]. - SeriesPartOf: There is no standard "SeriesPartOf" entity type or property in MusicBrainz. Instead, relationships are used to define connections between entities [4]. For example, the relationship type "part of" is commonly used to indicate that a release group belongs to a specific series [5]. You can look up the specific series associated with this identifier by appending the GUID to the MusicBrainz series URL: https://musicbrainz.org/series/8fe04b66-fe39-40ce-a28f-76b816d3f55a [1][3].

Citations:


🌐 Web query:

MusicBrainz Server Constants.pm 8da75c99-46ff-373c-9d31-276ca8fa8cc3

💡 Result:

In the MusicBrainz server codebase, the file lib/MusicBrainz/Server/Constants.pm is a Perl module used to define various constants and identifiers that have specific meanings within the database [1][2]. These constants include row IDs and Globally Unique Identifiers (GIDs) for special entities and system-level configuration parameters [1][2]. The UUID 8da75c99-46ff-373c-9d31-276ca8fa8cc3 is defined in the %PART_OF_SERIES hash within Constants.pm [1]. It specifically represents the Series entity type within the MusicBrainz database [1]. This mapping allows the server logic to programmatically identify and handle Series objects throughout the application [1][3]. The module typically contains: - Mappings for special entities (e.g., "Various Artists," "[no label]," "Deleted Artist") [1][2]. - Entity type GIDs (as seen with the Series GID) [1]. - Configuration for system behaviors, such as voting periods, edit listing limits, and sanitized dump generation [2][4]. By centralizing these values in Constants.pm, the MusicBrainz server ensures consistency when interacting with the database or performing entity-specific operations across different parts of the application [2][5].

Citations:


🌐 Web query:

MusicBrainz 8fe04b66-fe39-40ce-a28f-76b816d3f55a link_type series-series part of admin/sql/CreateViews.sql

💡 Result:

The MusicBrainz identifier 8fe04b66-fe39-40ce-a28f-76b816d3f55a corresponds to a specific link type in the MusicBrainz database [1][2]. Specifically, this UUID identifies the "part of" relationship type used within series-to-series links [3][1]. In the MusicBrainz database schema, the link_type table stores the definitions for relationship types [1][2]. The file admin/sql/CreateViews.sql in the musicbrainz-server repository is a SQL script used to define database views, which often join these link type tables with their corresponding relationship tables (such as l_series_series) to make querying easier [4]. Summary of key technical points: - Identifier: 8fe04b66-fe39-40ce-a28f-76b816d3f55a is the unique global identifier (GID) for the "part of" link type [3][1]. - Relationship: It is typically utilized in l_series_series relationships to indicate that one series is a part of another [3][5]. - Database Context: admin/sql/CreateViews.sql is part of the server infrastructure that manages how these relationship types are exposed and queried via SQL views [4].

Citations:


🌐 Web query:

MusicBrainz 8da75c99-46ff-373c-9d31-276ca8fa8cc3 admin/sql/CreateViews.sql series_series

💡 Result:

In the MusicBrainz database schema, series_series is a database view defined within the project's SQL administration scripts, specifically located in CreateViews.sql [1]. This view is designed to facilitate queries involving series-to-series relationships [1]. It typically joins tables such as l_series_series (the link table for series-to-series relationships), series (the main entity table), and associated link and attribute tables to allow for the retrieval of hierarchical or associative series data [1]. The reference 8da75c99-46ff-373c-9d31-276ca8fa8cc3 appears to be a commit hash or a specific identifier within the MusicBrainz server repository context [2], related to the management of these schema objects. The MusicBrainz database uses a series of SQL scripts found in the admin/sql directory of the musicbrainz-server codebase to manage the schema, including the creation of views, constraints, and tables [2][3][4][5]. Series entities in MusicBrainz represent sequences of release groups, releases, recordings, works, or events that share a common theme, often with numbering to indicate their position within the series [5].

Citations:


Use the part-of link_type gid in series_series.

8fe04b66-fe39-40ce-a28f-76b816d3f55a is defined for the series→series “part of” rel, while 8da75c99-46ff-373c-9d31-276ca8fa8cc3 is not the relation type this view is filtering. The view joins lt.gid, so the existing CREATE OR REPLACE VIEW copies become empty while the new rel rows use the other gid.

  • mbslave/sql/updates/20260121-mbs-14092.sql#L25
  • mbslave/sql/CreateViews.sql#L96
  • mbslave/sql/updates/schema-change/31.all.sql#L34
📍 Affects 3 files
  • mbslave/sql/updates/20260121-mbs-14092.sql#L15-L27 (this comment)
  • mbslave/sql/CreateViews.sql#L86-L98
  • mbslave/sql/updates/schema-change/31.all.sql#L24-L36
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mbslave/sql/updates/20260121-mbs-14092.sql` around lines 15 - 27, Update the
series_series view’s link_type gid filter to use the series→series part-of gid
8fe04b66-fe39-40ce-a28f-76b816d3f55a in
mbslave/sql/updates/20260121-mbs-14092.sql lines 15-27,
mbslave/sql/CreateViews.sql lines 86-98, and
mbslave/sql/updates/schema-change/31.all.sql lines 24-36; make the same
replacement in each view definition.

Comment on lines +79 to +81
INSERT INTO series_type (id, name, entity_type, parent, child_order, description, gid) VALUES
(16, 'Series series', 'series', NULL, 6, 'A series of series.', generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'series_type16')),
(17, 'Series award', 'series', 16, 0, 'A series of series (such as podcasts or festivals) honoured by the same award.', generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'series_type17'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

These inserts aren't idempotent, unlike every other insert in the file.

Every other seed statement here uses ON CONFLICT DO NOTHING; these two don't. A standalone DB that already carries series_type 16/17 (or the gids) will abort the whole upgrade transaction. Also check whether the series_type id sequence gets bumped past 17 somewhere (SetSequences), otherwise later inserts collide.

🔧 Match the surrounding style
 INSERT INTO series_type (id, name, entity_type, parent, child_order, description, gid) VALUES
     (16, 'Series series', 'series', NULL, 6, 'A series of series.', generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'series_type16')),
-    (17, 'Series award', 'series', 16, 0, 'A series of series (such as podcasts or festivals) honoured by the same award.', generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'series_type17'));
+    (17, 'Series award', 'series', 16, 0, 'A series of series (such as podcasts or festivals) honoured by the same award.', generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'series_type17'))
+    ON CONFLICT DO NOTHING;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
INSERT INTO series_type (id, name, entity_type, parent, child_order, description, gid) VALUES
(16, 'Series series', 'series', NULL, 6, 'A series of series.', generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'series_type16')),
(17, 'Series award', 'series', 16, 0, 'A series of series (such as podcasts or festivals) honoured by the same award.', generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'series_type17'));
INSERT INTO series_type (id, name, entity_type, parent, child_order, description, gid) VALUES
(16, 'Series series', 'series', NULL, 6, 'A series of series.', generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'series_type16')),
(17, 'Series award', 'series', 16, 0, 'A series of series (such as podcasts or festivals) honoured by the same award.', generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'series_type17'))
ON CONFLICT DO NOTHING;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mbslave/sql/updates/20260121-mbs-14092.sql` around lines 79 - 81, Update the
series_type seed INSERT for IDs 16 and 17 to use the file’s established ON
CONFLICT DO NOTHING pattern, preserving both rows’ values. Also update the
migration’s SetSequences handling so the series_type ID sequence is advanced
beyond 17 and later inserts cannot collide.

Comment on lines +22 to +28
pdcursor NO SCROLL CURSOR (oooseqid INTEGER) FOR
SELECT seqid
FROM dbmirror2.pending_data
WHERE xid = txid_current()
AND seqid >= oooseqid
ORDER BY seqid DESC
FOR UPDATE;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

pdcursor (oooseqid INTEGER) narrows a BIGSERIAL sequence id in all five copies of recordchange(). oooseqid is BIGINT; passing it into an INTEGER cursor parameter throws "integer out of range" once pending_data.seqid crosses 2^31, which kills every write on the database. Same one-word fix everywhere (keys TEXT[] is also declared and unused in each copy).

  • mbslave/sql/updates/20260502-search-756-master_only.sql#L22-L28: change the cursor parameter to BIGINT.
  • mbslave/sql/updates/20260507-search-756-mirror_only.sql#L22-L28: same change.
  • mbslave/sql/updates/20260507-search-756-standalone_only.sql#L25-L31: same change.
  • mbslave/sql/updates/schema-change/31.master_only.sql#L28-L34: regenerate from the corrected source.
  • mbslave/sql/updates/schema-change/31.mirror_only.sql#L28-L34: regenerate from the corrected source.

If these bodies are meant to stay byte-identical to the upstream MusicBrainz scripts, say so and I'll drop this — but then it's worth reporting upstream.

📍 Affects 5 files
  • mbslave/sql/updates/20260502-search-756-master_only.sql#L22-L28 (this comment)
  • mbslave/sql/updates/20260507-search-756-mirror_only.sql#L22-L28
  • mbslave/sql/updates/20260507-search-756-standalone_only.sql#L25-L31
  • mbslave/sql/updates/schema-change/31.master_only.sql#L28-L34
  • mbslave/sql/updates/schema-change/31.mirror_only.sql#L28-L34
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mbslave/sql/updates/20260502-search-756-master_only.sql` around lines 22 -
28, The pdcursor parameter in every recordchange() copy must use BIGINT to match
the BIGINT oooseqid and pending_data.seqid types. Update
mbslave/sql/updates/20260502-search-756-master_only.sql:22-28,
mbslave/sql/updates/20260507-search-756-mirror_only.sql:22-28, and
mbslave/sql/updates/20260507-search-756-standalone_only.sql:25-31; then
regenerate mbslave/sql/updates/schema-change/31.master_only.sql:28-34 and
mbslave/sql/updates/schema-change/31.mirror_only.sql:28-34 from the corrected
source.

Comment on lines +29 to +37
oooseqid BIGINT;
oootrgdepth INTEGER;
pdcursor NO SCROLL CURSOR (oooseqid INTEGER) FOR
SELECT seqid
FROM dbmirror2.pending_data
WHERE xid = txid_current()
AND seqid >= oooseqid
ORDER BY seqid DESC
FOR UPDATE;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does PostgreSQL PL/pgSQL implicitly assignment-cast a bigint argument into an integer-typed cursor parameter, and raise "integer out of range" on overflow?

💡 Result:

Yes, PostgreSQL will raise an "integer out of range" error if you attempt to pass a value that exceeds the range of the integer type into a PL/pgSQL cursor parameter defined as an integer. When a cursor is declared with parameters, those parameters have explicitly defined data types [1]. When the cursor is opened, the provided argument values are substituted into the cursor's query [1]. If an argument provided to the OPEN statement is of a broader type (such as bigint) and it is passed into a parameter defined as a narrower type (such as integer), PostgreSQL will attempt an implicit cast [2][3]. Because implicit casting from a larger integer type (bigint) to a smaller integer type (integer) is not a "widening" conversion, the operation is subject to range checks. If the value of the bigint argument is outside the valid range for the integer type (i.e., less than -2,147,483,648 or greater than 2,147,483,647), the cast will fail, resulting in an "integer out of range" error [4][5]. This behavior is consistent with standard PostgreSQL assignment and casting rules, where down-casting is not permitted for values that do not fit into the target type [2][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
git ls-files | rg '(^|/)31\.standalone_only\.sql$|(^|/)dbmirror2\.sql$' || true

echo
echo "== relevant file snippets =="
for f in mbslave/sql/updates/schema-change/31.standalone_only.sql mbslave/sql/dbmirror2/dbmirror2.sql; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    wc -l "$f"
    rg -n "oooseqid|pdcursor|seqid|recordchange|pending_data" "$f" -C 3
  fi
done

echo
echo "== parse/scan cursor declare and call sites =="
python3 - <<'PY'
from pathlib import Path
for path in [Path("mbslave/sql/updates/schema-change/31.standalone_only.sql"), Path("mbslave/sql/dbmirror2/dbmirror2.sql")]:
    if not path.exists():
        continue
    text = path.read_text()
    print(f"\n== {path} ==")
    for needle in ["oooseqid    BIGINT", "pdcursor    NO SCROLL CURSOR", "pdcursor(oooseqid := oooseqid)", "pdcursor (oooseqid := oooseqid)", "pdcursor(oooseqid := oooseqid)", "pdcursor(oooseqid"] :
        if needle in text:
            idx = text.index(needle)
            start = max(0, text.rfind("\n", 0, idx-200))
            end = min(len(text), text.find("\n", idx+2000))
            print(f"NEEDLE {repr(needle)} found")
            print(text[start:end])
PY

Repository: acoustid/mbslave

Length of output: 21960


Use BIGINT for the pdcursor out-of-order seqid parameter.

oooseqid and pending_data.seqid are BIGINT/BIGSERIAL, so a sequence value above 2147483647 cannot be assigned to the cursor parameter without failing integer out of range; this can break the trigger path when the queue is still active. Apply the same change to mbslave/sql/dbmirror2/dbmirror2.sql to keep the upstream mirror SQL consistent.

Proposed fix
-    pdcursor    NO SCROLL CURSOR (oooseqid INTEGER) FOR
+    pdcursor    NO SCROLL CURSOR (oooseqid BIGINT) FOR
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
oooseqid BIGINT;
oootrgdepth INTEGER;
pdcursor NO SCROLL CURSOR (oooseqid INTEGER) FOR
SELECT seqid
FROM dbmirror2.pending_data
WHERE xid = txid_current()
AND seqid >= oooseqid
ORDER BY seqid DESC
FOR UPDATE;
oooseqid BIGINT;
oootrgdepth INTEGER;
pdcursor NO SCROLL CURSOR (oooseqid BIGINT) FOR
SELECT seqid
FROM dbmirror2.pending_data
WHERE xid = txid_current()
AND seqid >= oooseqid
ORDER BY seqid DESC
FOR UPDATE;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mbslave/sql/updates/schema-change/31.standalone_only.sql` around lines 29 -
37, Change the pdcursor parameter type from INTEGER to BIGINT in the standalone
schema-change SQL and the corresponding dbmirror2 SQL definition, while leaving
the oooseqid declaration and cursor query behavior unchanged.

@lalinsky
lalinsky merged commit e2f69d3 into main Jul 26, 2026
10 checks passed
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.

1 participant