From c55c1395ab4ff16e444bc28729c345eea4b47e1e Mon Sep 17 00:00:00 2001 From: Harald Friessnegger Date: Fri, 23 May 2025 10:32:01 +0200 Subject: [PATCH 1/4] update to schema v30 see https://blog.metabrainz.org/2025/05/20/musicbrainz-database-schema-change-release-2025-05-19-with-upgrade-instructions/ for change notes --- CHANGELOG.rst | 5 +++++ README.rst | 10 +++++++++- mbslave/__init__.py | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 088e3ea..a036bf9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,8 @@ +Version 30.0.0 +============== + +- Schema change 30. + Version 29.1.0 ============== diff --git a/README.rst b/README.rst index 9e4dce3..211fd8a 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ MusicBrainz Database Mirror :target: https://badge.fury.io/py/mbslave This repository now contains a collection of scripts for managing a -replica of the MusicBrainz database. +replica of the MusicBrainz database. The main motivation for these scripts is to be able to customize your database. If you don't need such customizations, it might be @@ -82,6 +82,14 @@ When the MusicBrainz database schema changes, the replication will stop working. This is usually announced on the `MusicBrainz blog `__. When it happens, you need to upgrade the database. +Release 2025-05-19 (30) +~~~~~~~~~~~~~~~~~~~~~~~ + +Run the upgrade scripts:: + + mbslave psql -f updates/schema-change/30.all.sql + echo 'UPDATE replication_control SET current_schema_sequence = 30;' | mbslave psql + Release 2024-05-13 (29) ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/mbslave/__init__.py b/mbslave/__init__.py index 7c2f436..8cb7180 100644 --- a/mbslave/__init__.py +++ b/mbslave/__init__.py @@ -1,4 +1,4 @@ # Copyright (C) 2013 Lukas Lalinsky # Distributed under the MIT license, see the LICENSE file for details. -__version__ = "29.1.0" +__version__ = "30.0.0" From 084990c3d5060bf6146d25e598561b8a2200261b Mon Sep 17 00:00:00 2001 From: Harald Friessnegger Date: Fri, 23 May 2025 13:19:11 +0200 Subject: [PATCH 2/4] update sql scripts (via `./scripts/update_sql.sh`) note that this reverts the adaptions done by https://github.com/acoustid/mbslave/pull/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; ``` --- mbslave/sql/CreateFKConstraints.sql | 5 + mbslave/sql/CreateFunctions.sql | 367 ++++++++-------- mbslave/sql/CreateIndexes.sql | 11 +- mbslave/sql/CreateMirrorOnlyFunctions.sql | 36 +- mbslave/sql/CreateMirrorOnlyTriggers.sql | 21 + mbslave/sql/CreatePrimaryKeys.sql | 1 + mbslave/sql/CreateReplicationTriggers.sql | 4 + mbslave/sql/CreateReplicationTriggers2.sql | 4 + mbslave/sql/CreateTables.sql | 24 +- mbslave/sql/CreateTriggers.sql | 21 + mbslave/sql/DisableLastUpdatedTriggers.sql | 0 mbslave/sql/DropFKConstraints.sql | 1 + mbslave/sql/DropFunctions.sql | 2 + mbslave/sql/DropIndexes.sql | 2 + mbslave/sql/DropMirrorOnlyTriggers.sql | 4 + mbslave/sql/DropPrimaryKeys.sql | 1 + mbslave/sql/DropReplicationTriggers.sql | 1 + mbslave/sql/DropReplicationTriggers2.sql | 1 + mbslave/sql/DropTables.sql | 1 + mbslave/sql/DropTriggers.sql | 4 + mbslave/sql/EnableLastUpdatedTriggers.sql | 0 mbslave/sql/InsertTestData.sql | 14 +- mbslave/sql/TruncateTables.sql | 1 + mbslave/sql/caa/CreateMQTriggers.sql | 148 ------- mbslave/sql/caa/CreateViews.sql | 1 - mbslave/sql/caa/DropMQTriggers.sql | 19 - mbslave/sql/eaa/CreateMQTriggers.sql | 161 ------- mbslave/sql/eaa/CreateViews.sql | 1 - mbslave/sql/eaa/DropMQTriggers.sql | 21 - mbslave/sql/updates/20240221-mbs-13492.sql | 23 + mbslave/sql/updates/20240726-mbs-9373.sql | 9 + .../sql/updates/20241017-mbs-9253-13464.sql | 136 ++++++ ...0241017-mbs-9253-master_and_standalone.sql | 37 ++ .../updates/20241017-mbs-9253-mirror_only.sql | 31 ++ mbslave/sql/updates/20241125-mbs-13832.sql | 48 +++ .../sql/updates/20250320-mbs-13768-fks.sql | 12 + mbslave/sql/updates/20250320-mbs-13768.sql | 31 ++ mbslave/sql/updates/20250408-mbs-13322.sql | 15 + .../sql/updates/20250408-mbs-13964-all.sql | 34 ++ ...250425-mbs-13464-master_and_standalone.sql | 19 + mbslave/sql/updates/20250425-mbs-13464.sql | 81 ++++ mbslave/sql/updates/20250425-mbs-13966.sql | 50 +++ mbslave/sql/updates/schema-change/30.all.sql | 401 ++++++++++++++++++ .../30.master_and_standalone.sql | 74 ++++ .../updates/schema-change/30.mirror_only.sql | 37 ++ 45 files changed, 1355 insertions(+), 560 deletions(-) mode change 100755 => 100644 mbslave/sql/DisableLastUpdatedTriggers.sql mode change 100755 => 100644 mbslave/sql/EnableLastUpdatedTriggers.sql delete mode 100644 mbslave/sql/caa/CreateMQTriggers.sql delete mode 100644 mbslave/sql/caa/DropMQTriggers.sql delete mode 100644 mbslave/sql/eaa/CreateMQTriggers.sql delete mode 100644 mbslave/sql/eaa/DropMQTriggers.sql create mode 100644 mbslave/sql/updates/20240221-mbs-13492.sql create mode 100644 mbslave/sql/updates/20240726-mbs-9373.sql create mode 100644 mbslave/sql/updates/20241017-mbs-9253-13464.sql create mode 100644 mbslave/sql/updates/20241017-mbs-9253-master_and_standalone.sql create mode 100644 mbslave/sql/updates/20241017-mbs-9253-mirror_only.sql create mode 100644 mbslave/sql/updates/20241125-mbs-13832.sql create mode 100644 mbslave/sql/updates/20250320-mbs-13768-fks.sql create mode 100644 mbslave/sql/updates/20250320-mbs-13768.sql create mode 100644 mbslave/sql/updates/20250408-mbs-13322.sql create mode 100644 mbslave/sql/updates/20250408-mbs-13964-all.sql create mode 100644 mbslave/sql/updates/20250425-mbs-13464-master_and_standalone.sql create mode 100644 mbslave/sql/updates/20250425-mbs-13464.sql create mode 100644 mbslave/sql/updates/20250425-mbs-13966.sql create mode 100644 mbslave/sql/updates/schema-change/30.all.sql create mode 100644 mbslave/sql/updates/schema-change/30.master_and_standalone.sql create mode 100644 mbslave/sql/updates/schema-change/30.mirror_only.sql diff --git a/mbslave/sql/CreateFKConstraints.sql b/mbslave/sql/CreateFKConstraints.sql index eef896f..4a601f6 100644 --- a/mbslave/sql/CreateFKConstraints.sql +++ b/mbslave/sql/CreateFKConstraints.sql @@ -3006,6 +3006,11 @@ ALTER TABLE medium_format FOREIGN KEY (parent) REFERENCES medium_format(id); +ALTER TABLE medium_gid_redirect + ADD CONSTRAINT medium_gid_redirect_fk_new_id + FOREIGN KEY (new_id) + REFERENCES medium(id); + ALTER TABLE medium_index ADD CONSTRAINT medium_index_fk_medium FOREIGN KEY (medium) diff --git a/mbslave/sql/CreateFunctions.sql b/mbslave/sql/CreateFunctions.sql index 285d04e..047ccfa 100644 --- a/mbslave/sql/CreateFunctions.sql +++ b/mbslave/sql/CreateFunctions.sql @@ -13,7 +13,7 @@ CREATE OR REPLACE FUNCTION _median(INTEGER[]) RETURNS INTEGER AS $$ LIMIT 1 -- Subtracting (n + 1) % 2 creates a left bias OFFSET greatest(0, floor((select count(*) FROM q) / 2.0) - ((select count(*) + 1 FROM q) % 2)); -$$ LANGUAGE sql SET search_path = musicbrainz, public IMMUTABLE; +$$ LANGUAGE sql IMMUTABLE; CREATE AGGREGATE median(INTEGER) ( SFUNC=array_append, @@ -50,7 +50,7 @@ BEGIN value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0'); RETURN value::uuid; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION from_hex(t text) RETURNS integer AS $$ @@ -61,7 +61,7 @@ BEGIN RETURN r.hex; END LOOP; END -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public IMMUTABLE STRICT; +$$ LANGUAGE plpgsql IMMUTABLE STRICT; -- NameSpace_URL = '6ba7b8119dad11d180b400c04fd430c8' CREATE OR REPLACE FUNCTION generate_uuid_v3(namespace varchar, name varchar) RETURNS uuid @@ -84,7 +84,7 @@ BEGIN value = value || substr(bytes, 1+2*10, 12); return value::uuid; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public IMMUTABLE STRICT; +$$ LANGUAGE 'plpgsql' IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION inc_ref_count(tbl varchar, row_id integer, val integer) RETURNS void AS $$ @@ -94,7 +94,7 @@ BEGIN EXECUTE 'UPDATE ' || tbl || ' SET ref_count = ref_count + ' || val || ' WHERE id = ' || row_id; RETURN; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION dec_ref_count(tbl varchar, row_id integer, val integer) RETURNS void AS $$ DECLARE @@ -109,7 +109,7 @@ BEGIN EXECUTE 'UPDATE ' || tbl || ' SET ref_count = ref_count - ' || val || ' WHERE id = ' || row_id; RETURN; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION integer_date(year SMALLINT, month SMALLINT, day SMALLINT) RETURNS INTEGER AS $$ @@ -126,7 +126,7 @@ RETURNS INTEGER AS $$ )::INTEGER END ) -$$ LANGUAGE sql SET search_path = musicbrainz, public IMMUTABLE PARALLEL SAFE; +$$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE; ----------------------------------------------------------------------- -- area triggers @@ -149,7 +149,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- artist triggers @@ -161,7 +161,7 @@ BEGIN INSERT INTO artist_meta (id) VALUES (NEW.id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; -- Ensure attribute type allows free text if free text is added CREATE OR REPLACE FUNCTION ensure_artist_attribute_type_allows_text() @@ -180,7 +180,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- artist_credit triggers @@ -197,7 +197,7 @@ BEGIN -- artist_release_group. RAISE EXCEPTION 'Cannot update artist_credit_name'; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- editor triggers @@ -211,7 +211,7 @@ BEGIN END IF; RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- event triggers @@ -234,7 +234,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- event triggers @@ -246,7 +246,7 @@ BEGIN INSERT INTO event_meta (id) VALUES (NEW.id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- instrument triggers @@ -261,7 +261,7 @@ BEGIN ) INSERT INTO link_creditable_attribute_type (attribute_type) SELECT id FROM inserted_rows; RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION a_upd_instrument() RETURNS trigger AS $$ BEGIN @@ -272,7 +272,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION a_del_instrument() RETURNS trigger AS $$ BEGIN @@ -283,7 +283,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; -- Ensure attribute type allows free text if free text is added CREATE OR REPLACE FUNCTION ensure_instrument_attribute_type_allows_text() @@ -302,7 +302,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- label triggers @@ -313,7 +313,7 @@ BEGIN INSERT INTO label_meta (id) VALUES (NEW.id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; -- Ensure attribute type allows free text if free text is added CREATE OR REPLACE FUNCTION ensure_label_attribute_type_allows_text() @@ -332,7 +332,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- medium triggers @@ -355,7 +355,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- place triggers @@ -367,7 +367,7 @@ BEGIN INSERT INTO place_meta (id) VALUES (NEW.id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; -- Ensure attribute type allows free text if free text is added CREATE OR REPLACE FUNCTION ensure_place_attribute_type_allows_text() @@ -386,7 +386,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- recording triggers @@ -395,7 +395,7 @@ $$ LANGUAGE plpgsql SET search_path = musicbrainz, public; CREATE OR REPLACE FUNCTION median_track_length(recording_id integer) RETURNS integer AS $$ SELECT median(track.length) FROM track WHERE recording = $1; -$$ LANGUAGE sql SET search_path = musicbrainz, public; +$$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION b_upd_recording() RETURNS TRIGGER AS $$ BEGIN @@ -409,7 +409,7 @@ BEGIN NEW.last_updated = now(); RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_recording() RETURNS trigger AS $$ BEGIN @@ -417,7 +417,7 @@ BEGIN INSERT INTO recording_meta (id) VALUES (NEW.id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_recording() RETURNS trigger AS $$ BEGIN @@ -427,14 +427,14 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_recording() RETURNS trigger AS $$ BEGIN PERFORM dec_ref_count('artist_credit', OLD.artist_credit, 1); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; -- Ensure attribute type allows free text if free text is added CREATE OR REPLACE FUNCTION ensure_recording_attribute_type_allows_text() @@ -453,7 +453,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- release triggers @@ -471,7 +471,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (NEW.release_group); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_release() RETURNS trigger AS $$ BEGIN @@ -516,7 +516,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release() RETURNS trigger AS $$ BEGIN @@ -528,7 +528,40 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (OLD.release_group); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION a_upd_release_group_primary_type_mirror() +RETURNS trigger AS $$ +BEGIN + -- DO NOT modify any replicated tables in this function; it's used + -- by a trigger on mirrors. + IF (NEW.child_order IS DISTINCT FROM OLD.child_order) + THEN + INSERT INTO artist_release_group_pending_update ( + SELECT id FROM release_group + WHERE release_group.type = OLD.id + ); + END IF; + RETURN NULL; +END; +$$ LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION a_upd_release_group_secondary_type_mirror() +RETURNS trigger AS $$ +BEGIN + -- DO NOT modify any replicated tables in this function; it's used + -- by a trigger on mirrors. + IF (NEW.child_order IS DISTINCT FROM OLD.child_order) + THEN + INSERT INTO artist_release_group_pending_update ( + SELECT release_group + FROM release_group_secondary_type_join + WHERE secondary_type = OLD.id + ); + END IF; + RETURN NULL; +END; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_release_group_secondary_type_join() RETURNS trigger AS $$ @@ -536,7 +569,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (NEW.release_group); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release_group_secondary_type_join() RETURNS trigger AS $$ @@ -544,7 +577,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (OLD.release_group); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_release_label() RETURNS trigger AS $$ @@ -552,7 +585,7 @@ BEGIN INSERT INTO artist_release_pending_update VALUES (NEW.release); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_release_label() RETURNS trigger AS $$ @@ -562,7 +595,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release_label() RETURNS trigger AS $$ @@ -570,7 +603,7 @@ BEGIN INSERT INTO artist_release_pending_update VALUES (OLD.release); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; -- Ensure attribute type allows free text if free text is added CREATE OR REPLACE FUNCTION ensure_release_attribute_type_allows_text() @@ -589,7 +622,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- release_group triggers @@ -602,7 +635,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (NEW.id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_release_group() RETURNS trigger AS $$ BEGIN @@ -619,7 +652,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release_group() RETURNS trigger AS $$ BEGIN @@ -627,7 +660,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (OLD.id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION b_upd_release_group_secondary_type_join() RETURNS trigger AS $$ BEGIN @@ -639,7 +672,7 @@ BEGIN -- artist_release_group up-to-date. RAISE EXCEPTION 'Cannot update release_group_secondary_type_join'; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; -- Ensure attribute type allows free text if free text is added CREATE OR REPLACE FUNCTION ensure_release_group_attribute_type_allows_text() @@ -656,7 +689,7 @@ RETURNS trigger AS $$ ELSE RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- series triggers @@ -679,7 +712,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- track triggers @@ -703,7 +736,7 @@ BEGIN ); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_track() RETURNS trigger AS $$ BEGIN @@ -749,7 +782,7 @@ BEGIN PERFORM materialise_recording_length(NEW.recording); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_track() RETURNS trigger AS $$ BEGIN @@ -769,7 +802,7 @@ BEGIN ); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- work triggers @@ -780,7 +813,7 @@ BEGIN INSERT INTO work_meta (id) VALUES (NEW.id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; -- Ensure attribute type allows free text if free text is added CREATE OR REPLACE FUNCTION ensure_work_attribute_type_allows_text() @@ -798,7 +831,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- alternative tracklist triggers @@ -811,7 +844,7 @@ BEGIN END IF; RETURN; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION dec_nullable_artist_credit(row_id integer) RETURNS void AS $$ BEGIN @@ -820,14 +853,14 @@ BEGIN END IF; RETURN; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_alternative_release_or_track() RETURNS trigger AS $$ BEGIN PERFORM inc_nullable_artist_credit(NEW.artist_credit); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_alternative_release_or_track() RETURNS trigger AS $$ BEGIN @@ -837,21 +870,21 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_alternative_release_or_track() RETURNS trigger AS $$ BEGIN PERFORM dec_nullable_artist_credit(OLD.artist_credit); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_alternative_medium_track() RETURNS trigger AS $$ BEGIN PERFORM inc_ref_count('alternative_track', NEW.alternative_track, 1); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_alternative_medium_track() RETURNS trigger AS $$ BEGIN @@ -861,14 +894,14 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_alternative_medium_track() RETURNS trigger AS $$ BEGIN PERFORM dec_ref_count('alternative_track', OLD.alternative_track, 1); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- lastupdate triggers @@ -879,7 +912,7 @@ BEGIN NEW.last_updated = NOW(); RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_edit() RETURNS trigger AS $$ BEGIN @@ -889,14 +922,14 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION b_ins_edit_materialize_status() RETURNS trigger AS $$ BEGIN NEW.status = (SELECT status FROM edit WHERE id = NEW.edit); RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ------------------------ -- Collection deletion and hiding triggers @@ -916,7 +949,7 @@ RETURNS trigger AS $$ RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION del_collection_sub_on_delete() RETURNS trigger AS $$ @@ -928,7 +961,7 @@ RETURNS trigger AS $$ RETURN OLD; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION del_collection_sub_on_private() RETURNS trigger AS $$ @@ -946,7 +979,7 @@ RETURNS trigger AS $$ RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION restore_collection_sub_on_public() RETURNS trigger AS $$ @@ -961,7 +994,7 @@ RETURNS trigger AS $$ RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ------------------------ -- CD Lookup @@ -1005,7 +1038,7 @@ BEGIN RETURN str::cube; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public IMMUTABLE; +$$ LANGUAGE 'plpgsql' IMMUTABLE; CREATE OR REPLACE FUNCTION create_bounding_cube(durations INTEGER[], fuzzy INTEGER) RETURNS cube AS $$ DECLARE @@ -1059,7 +1092,7 @@ BEGIN RETURN str::cube; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public IMMUTABLE; +$$ LANGUAGE 'plpgsql' IMMUTABLE; ------------------------------------------------------------------- -- Maintain musicbrainz.release_first_release_date @@ -1087,7 +1120,7 @@ BEGIN ) ORDER BY release, year NULLS LAST, month NULLS LAST, day NULLS LAST'; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public STRICT; +$$ LANGUAGE 'plpgsql' STRICT; CREATE OR REPLACE FUNCTION set_release_first_release_date(release_id INTEGER) RETURNS VOID AS $$ @@ -1104,7 +1137,7 @@ BEGIN INSERT INTO artist_release_pending_update VALUES (release_id); END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public STRICT; +$$ LANGUAGE 'plpgsql' STRICT; ------------------------------------------------------------------- -- Maintain release_group_meta.first_release_date @@ -1117,9 +1150,10 @@ BEGIN first_release_date_day = first.day FROM ( SELECT rd.year, rd.month, rd.day - FROM release + FROM release_group + LEFT JOIN release ON release.release_group = release_group.id LEFT JOIN release_first_release_date rd ON (rd.release = release.id) - WHERE release.release_group = release_group_id + WHERE release_group.id = release_group_id ORDER BY rd.year NULLS LAST, rd.month NULLS LAST, @@ -1129,7 +1163,7 @@ BEGIN WHERE id = release_group_id; INSERT INTO artist_release_group_pending_update VALUES (release_group_id); END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ------------------------------------------------------------------- -- Maintain musicbrainz.recording_first_release_date @@ -1149,7 +1183,7 @@ BEGIN rd.month NULLS LAST, rd.day NULLS LAST'; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public STRICT; +$$ LANGUAGE 'plpgsql' STRICT; CREATE OR REPLACE FUNCTION set_recordings_first_release_dates(recording_ids INTEGER[]) RETURNS VOID AS $$ @@ -1164,7 +1198,19 @@ BEGIN format('track.recording = any(%L)', recording_ids) ); END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public STRICT; +$$ LANGUAGE 'plpgsql' STRICT; + +CREATE OR REPLACE FUNCTION set_mediums_recordings_first_release_dates(medium_ids INTEGER[]) +RETURNS VOID AS $$ +BEGIN + PERFORM set_recordings_first_release_dates(( + SELECT array_agg(recording) + FROM track + WHERE track.medium = any(medium_ids) + )); + RETURN; +END; +$$ LANGUAGE 'plpgsql' STRICT; CREATE OR REPLACE FUNCTION set_releases_recordings_first_release_dates(release_ids INTEGER[]) RETURNS VOID AS $$ @@ -1177,7 +1223,19 @@ BEGIN )); RETURN; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public STRICT; +$$ LANGUAGE 'plpgsql' STRICT; + +CREATE OR REPLACE FUNCTION a_upd_medium_mirror() +RETURNS trigger AS $$ +BEGIN + -- DO NOT modify any replicated tables in this function; it's used + -- by a trigger on mirrors. + IF NEW.release IS DISTINCT FROM OLD.release THEN + PERFORM set_mediums_recordings_first_release_dates(ARRAY[OLD.id]); + END IF; + RETURN NULL; +END; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_release_event() RETURNS TRIGGER AS $$ @@ -1196,7 +1254,7 @@ BEGIN RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_release_event() RETURNS TRIGGER AS $$ @@ -1227,7 +1285,7 @@ BEGIN RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release_event() RETURNS TRIGGER AS $$ @@ -1246,13 +1304,13 @@ BEGIN RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION deny_special_purpose_deletion() RETURNS trigger AS $$ BEGIN RAISE EXCEPTION 'Attempted to delete a special purpose row'; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ------------------------------------------------------------------- -- Ratings @@ -1284,7 +1342,7 @@ BEGIN entity_type::TEXT || '_rating_raw' ) USING entity_id; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION update_aggregate_rating_for_raw_insert() RETURNS trigger AS $$ @@ -1297,7 +1355,7 @@ BEGIN PERFORM update_aggregate_rating(entity_type, new_entity_id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION update_aggregate_rating_for_raw_update() RETURNS trigger AS $$ @@ -1319,7 +1377,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION update_aggregate_rating_for_raw_delete() RETURNS trigger AS $$ @@ -1332,7 +1390,7 @@ BEGIN PERFORM update_aggregate_rating(entity_type, old_entity_id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION delete_ratings(enttype TEXT, ids INTEGER[]) RETURNS TABLE(editor INT, rating SMALLINT) AS $$ @@ -1346,7 +1404,7 @@ BEGIN USING ids; RETURN; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ------------------------------------------------------------------- -- Prevent link attributes being used on links that don't support them @@ -1366,7 +1424,7 @@ BEGIN END IF; RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; -------------------------------------------------------------------------------- -- Remove unused link rows when a relationship is changed @@ -1390,53 +1448,17 @@ BEGIN RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION delete_unused_url(ids INTEGER[]) RETURNS VOID AS $$ -DECLARE - clear_up INTEGER[]; -BEGIN - SELECT ARRAY( - SELECT id FROM url url_row WHERE id = any(ids) - EXCEPT - SELECT url FROM edit_url JOIN edit ON (edit.id = edit_url.edit) WHERE edit.status = 1 - EXCEPT - SELECT entity1 FROM l_area_url - EXCEPT - SELECT entity1 FROM l_artist_url - EXCEPT - SELECT entity1 FROM l_event_url - EXCEPT - SELECT entity1 FROM l_genre_url - EXCEPT - SELECT entity1 FROM l_instrument_url - EXCEPT - SELECT entity1 FROM l_label_url - EXCEPT - SELECT entity1 FROM l_mood_url - EXCEPT - SELECT entity1 FROM l_place_url - EXCEPT - SELECT entity1 FROM l_recording_url - EXCEPT - SELECT entity1 FROM l_release_url - EXCEPT - SELECT entity1 FROM l_release_group_url - EXCEPT - SELECT entity1 FROM l_series_url - EXCEPT - SELECT entity1 FROM l_url_url - EXCEPT - SELECT entity0 FROM l_url_url - EXCEPT - SELECT entity0 FROM l_url_work - ) INTO clear_up; - - DELETE FROM url_gid_redirect WHERE new_id = any(clear_up); - DELETE FROM url WHERE id = any(clear_up); -END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +BEGIN + DELETE FROM url_gid_redirect WHERE new_id = any(ids); + DELETE FROM url WHERE id = any(ids); +EXCEPTION + WHEN foreign_key_violation THEN RETURN; +END; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION remove_unused_url() RETURNS TRIGGER AS $$ @@ -1455,7 +1477,7 @@ BEGIN RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION simplify_search_hints() RETURNS trigger AS $$ @@ -1474,7 +1496,7 @@ BEGIN END IF; RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION end_date_implies_ended() RETURNS trigger AS $$ @@ -1487,7 +1509,7 @@ BEGIN END IF; RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION end_area_implies_ended() RETURNS trigger AS $$ @@ -1498,7 +1520,7 @@ BEGIN END IF; RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION delete_orphaned_recordings() RETURNS TRIGGER @@ -1559,15 +1581,15 @@ AS $$ RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION padded_by_whitespace(TEXT) RETURNS boolean AS $$ SELECT btrim($1) <> $1; -$$ LANGUAGE sql SET search_path = musicbrainz, public IMMUTABLE; +$$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION controlled_for_whitespace(TEXT) RETURNS boolean AS $$ SELECT NOT padded_by_whitespace($1); -$$ LANGUAGE sql IMMUTABLE SET search_path = musicbrainz, public; +$$ LANGUAGE SQL IMMUTABLE SET search_path = musicbrainz, public; CREATE OR REPLACE FUNCTION update_aggregate_tag_count(entity_type taggable_entity_type, entity_id INTEGER, tag_id INTEGER, count_change SMALLINT) RETURNS VOID AS $$ @@ -1583,7 +1605,7 @@ BEGIN entity_type::TEXT ) USING entity_id, tag_id, count_change; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION delete_unused_aggregate_tag(entity_type taggable_entity_type, entity_id INTEGER, tag_id INTEGER) RETURNS VOID AS $$ @@ -1606,7 +1628,7 @@ BEGIN entity_type::TEXT || '_tag_raw' ) USING entity_id, tag_id; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION update_tag_counts_for_raw_insert() RETURNS trigger AS $$ @@ -1620,7 +1642,7 @@ BEGIN UPDATE tag SET ref_count = ref_count + 1 WHERE id = NEW.tag; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION update_tag_counts_for_raw_update() RETURNS trigger AS $$ @@ -1647,7 +1669,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION update_tag_counts_for_raw_delete() RETURNS trigger AS $$ @@ -1662,7 +1684,7 @@ BEGIN UPDATE tag SET ref_count = ref_count - 1 WHERE id = OLD.tag; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION delete_unused_tag(tag_id INT) RETURNS void AS $$ @@ -1671,7 +1693,7 @@ RETURNS void AS $$ EXCEPTION WHEN foreign_key_violation THEN RETURN; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION trg_delete_unused_tag() RETURNS trigger AS $$ @@ -1679,7 +1701,7 @@ RETURNS trigger AS $$ PERFORM delete_unused_tag(NEW.id); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION trg_delete_unused_tag_ref() RETURNS trigger AS $$ @@ -1687,7 +1709,7 @@ RETURNS trigger AS $$ PERFORM delete_unused_tag(OLD.tag); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION inserting_edits_requires_confirmed_email_address() RETURNS trigger AS $$ @@ -1702,7 +1724,7 @@ BEGIN RETURN NEW; END IF; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION deny_deprecated_links() RETURNS trigger AS $$ @@ -1713,7 +1735,7 @@ BEGIN END IF; RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION check_has_dates() RETURNS trigger AS $$ @@ -1731,7 +1753,7 @@ BEGIN END IF; RETURN NEW; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION materialise_recording_length(recording_id INT) RETURNS void as $$ @@ -1741,14 +1763,14 @@ BEGIN WHERE recording.id = recording_id AND recording.length IS DISTINCT FROM track.median; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION track_count_matches_cdtoc(medium, int) RETURNS boolean AS $$ SELECT $1.track_count = $2 + COALESCE( (SELECT count(*) FROM track WHERE medium = $1.id AND (position = 0 OR is_data_track = true) ), 0); -$$ LANGUAGE sql SET search_path = musicbrainz, public IMMUTABLE; +$$ LANGUAGE SQL IMMUTABLE; COMMIT; @@ -1766,7 +1788,7 @@ BEGIN ); RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- Text search helpers @@ -1774,7 +1796,7 @@ $$ LANGUAGE plpgsql SET search_path = musicbrainz, public; CREATE OR REPLACE FUNCTION mb_lower(input text) RETURNS text AS $$ SELECT lower(input COLLATE musicbrainz.musicbrainz); -$$ LANGUAGE sql SET search_path = musicbrainz, public IMMUTABLE PARALLEL SAFE STRICT; +$$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE STRICT; CREATE OR REPLACE FUNCTION mb_simple_tsvector(input text) RETURNS tsvector AS $$ -- The builtin 'simple' dictionary, which the mb_simple text search @@ -1782,7 +1804,7 @@ CREATE OR REPLACE FUNCTION mb_simple_tsvector(input text) RETURNS tsvector AS $$ -- for us, but internally it hardcodes DEFAULT_COLLATION_OID; therefore -- we first lowercase the input string ourselves using mb_lower. SELECT to_tsvector('musicbrainz.mb_simple', musicbrainz.mb_lower(input)); -$$ LANGUAGE sql SET search_path = musicbrainz, public IMMUTABLE PARALLEL SAFE STRICT; +$$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE STRICT; ----------------------------------------------------------------------- -- Edit data helpers @@ -1817,7 +1839,7 @@ BEGIN END CASE; RETURN ''; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public IMMUTABLE PARALLEL SAFE STRICT; +$$ LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE STRICT; ----------------------------------------------------------------------- -- Maintain musicbrainz.artist_release @@ -1844,7 +1866,7 @@ BEGIN (CASE r.barcode WHEN '' THEN '0' ELSE r.barcode END), '[^0-9]+', '', 'g' ), 18)::BIGINT AS barcode, - left(r.name, 1)::CHAR(1) AS sort_character, + r.name, r.id FROM ( SELECT FALSE AS is_track_artist, racn.artist, r.id AS release @@ -1868,7 +1890,7 @@ BEGIN $SQL$ USING release_id; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION apply_artist_release_pending_updates() RETURNS trigger AS $$ @@ -1908,7 +1930,7 @@ BEGIN RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- Maintain musicbrainz.artist_release_group @@ -1928,7 +1950,12 @@ BEGIN a_rg.artist, -- Withdrawn releases were once official by definition bool_and(r.status IS NOT NULL AND r.status != 1 AND r.status != 5), + rgpt.child_order::SMALLINT, rg.type::SMALLINT, + array_agg( + DISTINCT rgst.child_order ORDER BY rgst.child_order) + FILTER (WHERE rgst.child_order IS NOT NULL + )::SMALLINT[], array_agg( DISTINCT st.secondary_type ORDER BY st.secondary_type) FILTER (WHERE st.secondary_type IS NOT NULL @@ -1938,7 +1965,7 @@ BEGIN rgm.first_release_date_month, rgm.first_release_date_day ), - left(rg.name, 1)::CHAR(1), + rg.name, rg.id FROM ( SELECT FALSE AS is_track_artist, rgacn.artist, rg.id AS release_group @@ -1954,15 +1981,17 @@ BEGIN JOIN release_group rg ON rg.id = a_rg.release_group LEFT JOIN release r ON r.release_group = rg.id JOIN release_group_meta rgm ON rgm.id = rg.id + LEFT JOIN release_group_primary_type rgpt ON rgpt.id = rg.type LEFT JOIN release_group_secondary_type_join st ON st.release_group = rg.id + LEFT JOIN release_group_secondary_type rgst ON rgst.id = st.secondary_type $SQL$ || (CASE WHEN release_group_id IS NULL THEN '' ELSE 'WHERE rg.id = $1' END) || $SQL$ - GROUP BY a_rg.is_track_artist, a_rg.artist, rgm.id, rg.id + GROUP BY a_rg.is_track_artist, a_rg.artist, rgm.id, rg.id, rgpt.child_order ORDER BY a_rg.artist, rg.id, a_rg.is_track_artist $SQL$ USING release_group_id; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION apply_artist_release_group_pending_updates() RETURNS trigger AS $$ @@ -2002,7 +2031,7 @@ BEGIN RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- Relationship triggers @@ -2019,7 +2048,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION a_upd_l_area_area_mirror() RETURNS trigger AS $$ DECLARE @@ -2043,7 +2072,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION a_del_l_area_area_mirror() RETURNS trigger AS $$ DECLARE @@ -2056,7 +2085,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION b_upd_link() RETURNS trigger AS $$ BEGIN @@ -2069,28 +2098,28 @@ BEGIN -- area_containment. RAISE EXCEPTION 'link rows are immutable'; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION b_upd_link_attribute() RETURNS trigger AS $$ BEGIN -- Refer to b_upd_link. RAISE EXCEPTION 'link_attribute rows are immutable'; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION b_upd_link_attribute_credit() RETURNS trigger AS $$ BEGIN -- Refer to b_upd_link. RAISE EXCEPTION 'link_attribute_credit rows are immutable'; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION b_upd_link_attribute_text_value() RETURNS trigger AS $$ BEGIN -- Refer to b_upd_link. RAISE EXCEPTION 'link_attribute_text_value rows are immutable'; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; ----------------------------------------------------------------------- -- Maintain musicbrainz.area_containment @@ -2131,7 +2160,7 @@ BEGIN $SQL$ USING part_of_area_link_type_id, descendant_area_ids; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; -- Returns a set of area_containment rows that cover the entire descendant -- hierarchy for parent_area_ids. If NULL is passed, the entire @@ -2168,7 +2197,7 @@ BEGIN $SQL$ USING part_of_area_link_type_id, parent_area_ids; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION update_area_containment_mirror( parent_ids INTEGER[], -- entity0 of area-area "part of" @@ -2216,6 +2245,6 @@ BEGIN ) area_hierarchy ORDER BY descendant, parent, depth; END; -$$ LANGUAGE plpgsql SET search_path = musicbrainz, public; +$$ LANGUAGE plpgsql; -- vi: set ts=4 sw=4 et : diff --git a/mbslave/sql/CreateIndexes.sql b/mbslave/sql/CreateIndexes.sql index b5c0b69..8f48262 100644 --- a/mbslave/sql/CreateIndexes.sql +++ b/mbslave/sql/CreateIndexes.sql @@ -69,16 +69,16 @@ CREATE INDEX artist_rating_raw_idx_editor ON artist_rating_raw (editor); CREATE INDEX artist_tag_raw_idx_tag ON artist_tag_raw (tag); CREATE INDEX artist_tag_raw_idx_editor ON artist_tag_raw (editor); -CREATE INDEX artist_release_nonva_idx_sort ON artist_release_nonva (artist, first_release_date NULLS LAST, catalog_numbers NULLS LAST, country_code NULLS LAST, barcode NULLS LAST, sort_character, release); -CREATE INDEX artist_release_va_idx_sort ON artist_release_va (artist, first_release_date NULLS LAST, catalog_numbers NULLS LAST, country_code NULLS LAST, barcode NULLS LAST, sort_character, release); +CREATE INDEX artist_release_nonva_idx_sort ON artist_release_nonva (artist, first_release_date NULLS LAST, catalog_numbers NULLS LAST, country_code NULLS LAST, barcode NULLS LAST, name, release); +CREATE INDEX artist_release_va_idx_sort ON artist_release_va (artist, first_release_date NULLS LAST, catalog_numbers NULLS LAST, country_code NULLS LAST, barcode NULLS LAST, name, release); CREATE UNIQUE INDEX artist_release_nonva_idx_uniq ON artist_release_nonva (release, artist); CREATE UNIQUE INDEX artist_release_va_idx_uniq ON artist_release_va (release, artist); CREATE INDEX artist_release_pending_update_idx_release ON artist_release_pending_update USING HASH (release); -CREATE INDEX artist_release_group_nonva_idx_sort ON artist_release_group_nonva (artist, unofficial, primary_type NULLS FIRST, secondary_types NULLS FIRST, first_release_date NULLS LAST, sort_character, release_group); -CREATE INDEX artist_release_group_va_idx_sort ON artist_release_group_va (artist, unofficial, primary_type NULLS FIRST, secondary_types NULLS FIRST, first_release_date NULLS LAST, sort_character, release_group); +CREATE INDEX artist_release_group_nonva_idx_sort ON artist_release_group_nonva (artist, unofficial, primary_type_child_order NULLS FIRST, primary_type NULLS FIRST, secondary_type_child_orders NULLS FIRST, secondary_types NULLS FIRST, first_release_date NULLS LAST, name, release_group); +CREATE INDEX artist_release_group_va_idx_sort ON artist_release_group_va (artist, unofficial, primary_type_child_order NULLS FIRST, primary_type NULLS FIRST, secondary_type_child_orders NULLS FIRST, secondary_types NULLS FIRST, first_release_date NULLS LAST, name, release_group); CREATE UNIQUE INDEX artist_release_group_nonva_idx_uniq ON artist_release_group_nonva (release_group, artist); CREATE UNIQUE INDEX artist_release_group_va_idx_uniq ON artist_release_group_va (release_group, artist); @@ -507,6 +507,8 @@ CREATE UNIQUE INDEX editor_collection_type_idx_gid ON editor_collection_type (gi CREATE UNIQUE INDEX cdtoc_idx_discid ON cdtoc (discid); CREATE INDEX cdtoc_idx_freedb_id ON cdtoc (freedb_id); +CREATE UNIQUE INDEX medium_idx_gid ON medium (gid); + CREATE INDEX medium_attribute_idx_medium ON medium_attribute (medium); CREATE UNIQUE INDEX medium_attribute_type_idx_gid ON medium_attribute_type (gid); @@ -731,6 +733,7 @@ CREATE INDEX editor_collection_gid_redirect_idx_new_id ON editor_collection_gid_ CREATE INDEX event_gid_redirect_idx_new_id ON event_gid_redirect (new_id); CREATE INDEX instrument_gid_redirect_idx_new_id ON instrument_gid_redirect (new_id); CREATE INDEX label_gid_redirect_idx_new_id ON label_gid_redirect (new_id); +CREATE INDEX medium_gid_redirect_idx_new_id ON medium_gid_redirect (new_id); CREATE INDEX place_gid_redirect_idx_new_id ON place_gid_redirect (new_id); CREATE INDEX recording_gid_redirect_idx_new_id ON recording_gid_redirect (new_id); CREATE INDEX release_gid_redirect_idx_new_id ON release_gid_redirect (new_id); diff --git a/mbslave/sql/CreateMirrorOnlyFunctions.sql b/mbslave/sql/CreateMirrorOnlyFunctions.sql index 915d6e8..4836bf6 100644 --- a/mbslave/sql/CreateMirrorOnlyFunctions.sql +++ b/mbslave/sql/CreateMirrorOnlyFunctions.sql @@ -9,7 +9,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (NEW.release_group); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_release_mirror() RETURNS trigger AS $$ @@ -31,7 +31,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release_mirror() RETURNS trigger AS $$ @@ -40,7 +40,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (OLD.release_group); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_release_event_mirror() RETURNS trigger AS $$ @@ -52,7 +52,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_release_event_mirror() RETURNS trigger AS $$ @@ -67,7 +67,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release_event_mirror() RETURNS trigger AS $$ @@ -79,7 +79,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_release_group_mirror() RETURNS trigger AS $$ @@ -87,7 +87,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (NEW.id); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_release_group_mirror() RETURNS trigger AS $$ @@ -101,7 +101,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release_group_mirror() RETURNS trigger AS $$ @@ -109,7 +109,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (OLD.id); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_release_group_meta_mirror() RETURNS trigger AS $$ @@ -123,7 +123,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_release_group_secondary_type_join_mirror() RETURNS trigger AS $$ @@ -131,7 +131,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (NEW.release_group); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release_group_secondary_type_join_mirror() RETURNS trigger AS $$ @@ -139,7 +139,7 @@ BEGIN INSERT INTO artist_release_group_pending_update VALUES (OLD.release_group); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_release_label_mirror() RETURNS trigger AS $$ @@ -147,7 +147,7 @@ BEGIN INSERT INTO artist_release_pending_update VALUES (NEW.release); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_release_label_mirror() RETURNS trigger AS $$ @@ -157,7 +157,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_release_label_mirror() RETURNS trigger AS $$ @@ -165,7 +165,7 @@ BEGIN INSERT INTO artist_release_pending_update VALUES (OLD.release); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_ins_track_mirror() RETURNS trigger AS $$ @@ -182,7 +182,7 @@ BEGIN ); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_upd_track_mirror() RETURNS trigger AS $$ @@ -203,7 +203,7 @@ BEGIN END IF; RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; CREATE OR REPLACE FUNCTION a_del_track_mirror() RETURNS trigger AS $$ @@ -220,6 +220,6 @@ BEGIN ); RETURN NULL; END; -$$ LANGUAGE 'plpgsql' SET search_path = musicbrainz, public; +$$ LANGUAGE 'plpgsql'; COMMIT; diff --git a/mbslave/sql/CreateMirrorOnlyTriggers.sql b/mbslave/sql/CreateMirrorOnlyTriggers.sql index 999542a..9875d9d 100644 --- a/mbslave/sql/CreateMirrorOnlyTriggers.sql +++ b/mbslave/sql/CreateMirrorOnlyTriggers.sql @@ -24,6 +24,9 @@ CREATE TRIGGER a_upd_l_area_area_mirror AFTER UPDATE ON l_area_area CREATE TRIGGER a_del_l_area_area_mirror AFTER DELETE ON l_area_area FOR EACH ROW EXECUTE PROCEDURE a_del_l_area_area_mirror(); +CREATE TRIGGER a_upd_medium AFTER UPDATE ON medium + FOR EACH ROW EXECUTE PROCEDURE a_upd_medium_mirror(); + CREATE TRIGGER a_ins_release_mirror AFTER INSERT ON release FOR EACH ROW EXECUTE PROCEDURE a_ins_release_mirror(); @@ -63,6 +66,12 @@ CREATE TRIGGER a_del_release_group_mirror AFTER DELETE ON release_group CREATE TRIGGER a_upd_release_group_meta_mirror AFTER UPDATE ON release_group_meta FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_meta_mirror(); +CREATE TRIGGER a_upd_release_group_primary_type_mirror AFTER UPDATE ON release_group_primary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_primary_type_mirror(); + +CREATE TRIGGER a_upd_release_group_secondary_type_mirror AFTER UPDATE ON release_group_secondary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_secondary_type_mirror(); + CREATE TRIGGER a_ins_release_group_secondary_type_join_mirror AFTER INSERT ON release_group_secondary_type_join FOR EACH ROW EXECUTE PROCEDURE a_ins_release_group_secondary_type_join_mirror(); @@ -111,6 +120,18 @@ CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates_mirror AFTER UPDATE ON release_group_meta DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates_mirror + AFTER UPDATE ON release_group_primary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates_mirror + AFTER UPDATE ON release_group_secondary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates_mirror AFTER INSERT OR DELETE ON release_group_secondary_type_join DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); diff --git a/mbslave/sql/CreatePrimaryKeys.sql b/mbslave/sql/CreatePrimaryKeys.sql index 8724bab..7b1fb0f 100644 --- a/mbslave/sql/CreatePrimaryKeys.sql +++ b/mbslave/sql/CreatePrimaryKeys.sql @@ -264,6 +264,7 @@ ALTER TABLE medium_attribute_type_allowed_value ADD CONSTRAINT medium_attribute_ ALTER TABLE medium_attribute_type_allowed_value_allowed_format ADD CONSTRAINT medium_attribute_type_allowed_value_allowed_format_pkey PRIMARY KEY (medium_format, medium_attribute_type_allowed_value); ALTER TABLE medium_cdtoc ADD CONSTRAINT medium_cdtoc_pkey PRIMARY KEY (id); ALTER TABLE medium_format ADD CONSTRAINT medium_format_pkey PRIMARY KEY (id); +ALTER TABLE medium_gid_redirect ADD CONSTRAINT medium_gid_redirect_pkey PRIMARY KEY (gid); ALTER TABLE medium_index ADD CONSTRAINT medium_index_pkey PRIMARY KEY (medium); ALTER TABLE mood ADD CONSTRAINT mood_pkey PRIMARY KEY (id); ALTER TABLE mood_alias ADD CONSTRAINT mood_alias_pkey PRIMARY KEY (id); diff --git a/mbslave/sql/CreateReplicationTriggers.sql b/mbslave/sql/CreateReplicationTriggers.sql index f35f62d..d989a20 100644 --- a/mbslave/sql/CreateReplicationTriggers.sql +++ b/mbslave/sql/CreateReplicationTriggers.sql @@ -815,6 +815,10 @@ CREATE TRIGGER "reptg_medium_format" AFTER INSERT OR DELETE OR UPDATE ON "medium_format" FOR EACH ROW EXECUTE PROCEDURE "recordchange" (); +CREATE TRIGGER "reptg_medium_gid_redirect" +AFTER INSERT OR DELETE OR UPDATE ON "medium_gid_redirect" +FOR EACH ROW EXECUTE PROCEDURE "recordchange" ('verbose'); + CREATE TRIGGER "reptg_medium_index" AFTER INSERT OR DELETE OR UPDATE ON "medium_index" FOR EACH ROW EXECUTE PROCEDURE "recordchange" (); diff --git a/mbslave/sql/CreateReplicationTriggers2.sql b/mbslave/sql/CreateReplicationTriggers2.sql index 1727b0a..28ff024 100644 --- a/mbslave/sql/CreateReplicationTriggers2.sql +++ b/mbslave/sql/CreateReplicationTriggers2.sql @@ -815,6 +815,10 @@ CREATE TRIGGER reptg2_medium_format AFTER INSERT OR DELETE OR UPDATE ON medium_format FOR EACH ROW EXECUTE PROCEDURE dbmirror2.recordchange(); +CREATE TRIGGER reptg2_medium_gid_redirect +AFTER INSERT OR DELETE OR UPDATE ON medium_gid_redirect +FOR EACH ROW EXECUTE PROCEDURE dbmirror2.recordchange(); + CREATE TRIGGER reptg2_medium_index AFTER INSERT OR DELETE OR UPDATE ON medium_index FOR EACH ROW EXECUTE PROCEDURE dbmirror2.recordchange(); diff --git a/mbslave/sql/CreateTables.sql b/mbslave/sql/CreateTables.sql index 7f3fabe..73cca4b 100644 --- a/mbslave/sql/CreateTables.sql +++ b/mbslave/sql/CreateTables.sql @@ -429,15 +429,7 @@ CREATE TABLE artist_release ( catalog_numbers TEXT[], country_code CHAR(2), barcode BIGINT, - -- Prior to adding these materialized tables, we'd order releases - -- by name only if all other attributes where equal. It's not too - -- common that an artist will have tons of releases with no dates, - -- catalog numbers, countries, or barcodes (though it can be seen - -- on some big composers). As a compromise between dropping the - -- name sorting and having to store the entire name here (which, - -- as a reminder, is duplicated for every artist on the release), - -- we only store the first character of the name for sorting. - sort_character CHAR(1) COLLATE musicbrainz NOT NULL, + name VARCHAR COLLATE musicbrainz NOT NULL, release INTEGER NOT NULL -- references release.id, CASCADE ) PARTITION BY LIST (is_track_artist); @@ -466,11 +458,12 @@ CREATE TABLE artist_release_group ( is_track_artist BOOLEAN NOT NULL, artist INTEGER NOT NULL, -- references artist.id, CASCADE unofficial BOOLEAN NOT NULL, + primary_type_child_order SMALLINT, primary_type SMALLINT, + secondary_type_child_orders SMALLINT[], secondary_types SMALLINT[], first_release_date INTEGER, - -- See comment for `artist_release.sort_character`. - sort_character CHAR(1) COLLATE musicbrainz NOT NULL, + name VARCHAR COLLATE musicbrainz NOT NULL, release_group INTEGER NOT NULL -- references release_group.id, CASCADE ) PARTITION BY LIST (is_track_artist); @@ -2907,7 +2900,8 @@ CREATE TABLE medium ( -- replicate (verbose) name VARCHAR NOT NULL DEFAULT '', edits_pending INTEGER NOT NULL DEFAULT 0 CHECK (edits_pending >= 0), last_updated TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - track_count INTEGER NOT NULL DEFAULT 0 + track_count INTEGER NOT NULL DEFAULT 0, + gid UUID NOT NULL ); CREATE TABLE medium_attribute_type ( -- replicate (verbose) @@ -2973,6 +2967,12 @@ CREATE TABLE medium_format ( -- replicate gid uuid NOT NULL ); +CREATE TABLE medium_gid_redirect ( -- replicate (verbose) + gid UUID NOT NULL, -- PK + new_id INTEGER NOT NULL, -- references medium.id + created TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + CREATE TABLE mood ( -- replicate (verbose) id SERIAL, -- PK gid UUID NOT NULL, diff --git a/mbslave/sql/CreateTriggers.sql b/mbslave/sql/CreateTriggers.sql index 148c7f8..7f5ee5c 100644 --- a/mbslave/sql/CreateTriggers.sql +++ b/mbslave/sql/CreateTriggers.sql @@ -454,6 +454,9 @@ CREATE TRIGGER b_upd_link_type BEFORE UPDATE ON link_type CREATE TRIGGER b_upd_link_type_attribute_type BEFORE UPDATE ON link_type_attribute_type FOR EACH ROW EXECUTE PROCEDURE b_upd_last_updated_table(); +CREATE TRIGGER a_upd_medium AFTER UPDATE ON medium + FOR EACH ROW EXECUTE PROCEDURE a_upd_medium_mirror(); + CREATE TRIGGER b_upd_medium BEFORE UPDATE ON medium FOR EACH ROW EXECUTE PROCEDURE b_upd_last_updated_table(); @@ -580,6 +583,12 @@ CREATE TRIGGER a_del_release_group AFTER DELETE ON release_group CREATE TRIGGER b_upd_release_group BEFORE UPDATE ON release_group FOR EACH ROW EXECUTE PROCEDURE b_upd_last_updated_table(); +CREATE TRIGGER a_upd_release_group_primary_type AFTER UPDATE ON release_group_primary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_primary_type_mirror(); + +CREATE TRIGGER a_upd_release_group_secondary_type AFTER UPDATE ON release_group_secondary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_secondary_type_mirror(); + CREATE TRIGGER a_ins_release_group_secondary_type_join AFTER INSERT ON release_group_secondary_type_join FOR EACH ROW EXECUTE PROCEDURE a_ins_release_group_secondary_type_join(); @@ -1299,6 +1308,18 @@ CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates AFTER UPDATE ON release_group_meta DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates + AFTER UPDATE ON release_group_primary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates + AFTER UPDATE ON release_group_secondary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates AFTER INSERT OR DELETE ON release_group_secondary_type_join DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); diff --git a/mbslave/sql/DisableLastUpdatedTriggers.sql b/mbslave/sql/DisableLastUpdatedTriggers.sql old mode 100755 new mode 100644 diff --git a/mbslave/sql/DropFKConstraints.sql b/mbslave/sql/DropFKConstraints.sql index 0d4eadf..5c03596 100644 --- a/mbslave/sql/DropFKConstraints.sql +++ b/mbslave/sql/DropFKConstraints.sql @@ -597,6 +597,7 @@ ALTER TABLE medium_attribute_type_allowed_value_allowed_format DROP CONSTRAINT I ALTER TABLE medium_cdtoc DROP CONSTRAINT IF EXISTS medium_cdtoc_fk_medium; ALTER TABLE medium_cdtoc DROP CONSTRAINT IF EXISTS medium_cdtoc_fk_cdtoc; ALTER TABLE medium_format DROP CONSTRAINT IF EXISTS medium_format_fk_parent; +ALTER TABLE medium_gid_redirect DROP CONSTRAINT IF EXISTS medium_gid_redirect_fk_new_id; ALTER TABLE medium_index DROP CONSTRAINT IF EXISTS medium_index_fk_medium; ALTER TABLE mood_alias DROP CONSTRAINT IF EXISTS mood_alias_fk_mood; ALTER TABLE mood_alias DROP CONSTRAINT IF EXISTS mood_alias_fk_type; diff --git a/mbslave/sql/DropFunctions.sql b/mbslave/sql/DropFunctions.sql index e37ad16..0bb2472 100644 --- a/mbslave/sql/DropFunctions.sql +++ b/mbslave/sql/DropFunctions.sql @@ -39,6 +39,8 @@ DROP FUNCTION a_upd_recording(); DROP FUNCTION a_upd_release(); DROP FUNCTION a_upd_release_event(); DROP FUNCTION a_upd_release_group(); +DROP FUNCTION a_upd_release_group_primary_type_mirror(); +DROP FUNCTION a_upd_release_group_secondary_type_mirror(); DROP FUNCTION a_upd_release_label(); DROP FUNCTION a_upd_track(); DROP FUNCTION apply_artist_release_group_pending_updates(); diff --git a/mbslave/sql/DropIndexes.sql b/mbslave/sql/DropIndexes.sql index 4e83c1e..a9b8e00 100644 --- a/mbslave/sql/DropIndexes.sql +++ b/mbslave/sql/DropIndexes.sql @@ -403,6 +403,8 @@ DROP INDEX medium_cdtoc_idx_cdtoc; DROP INDEX medium_cdtoc_idx_medium; DROP INDEX medium_cdtoc_idx_uniq; DROP INDEX medium_format_idx_gid; +DROP INDEX medium_gid_redirect_idx_new_id; +DROP INDEX medium_idx_gid; DROP INDEX medium_idx_track_count; DROP INDEX medium_index_idx; DROP INDEX mood_alias_idx_mood; diff --git a/mbslave/sql/DropMirrorOnlyTriggers.sql b/mbslave/sql/DropMirrorOnlyTriggers.sql index 136d008..e7a9b17 100644 --- a/mbslave/sql/DropMirrorOnlyTriggers.sql +++ b/mbslave/sql/DropMirrorOnlyTriggers.sql @@ -17,6 +17,8 @@ DROP TRIGGER IF EXISTS a_ins_release_group_mirror ON release_group; DROP TRIGGER IF EXISTS a_upd_release_group_mirror ON release_group; DROP TRIGGER IF EXISTS a_del_release_group_mirror ON release_group; DROP TRIGGER IF EXISTS a_upd_release_group_meta_mirror ON release_group_meta; +DROP TRIGGER IF EXISTS a_upd_release_group_primary_type_mirror ON release_group_primary_type; +DROP TRIGGER IF EXISTS a_upd_release_group_secondary_type_mirror ON release_group_secondary_type; DROP TRIGGER IF EXISTS a_ins_release_group_secondary_type_join_mirror ON release_group_secondary_type_join; DROP TRIGGER IF EXISTS a_del_release_group_secondary_type_join_mirror ON release_group_secondary_type_join; DROP TRIGGER IF EXISTS a_ins_release_label_mirror ON release_label; @@ -31,6 +33,8 @@ DROP TRIGGER IF EXISTS apply_artist_release_pending_updates_mirror ON release_co DROP TRIGGER IF EXISTS apply_artist_release_pending_updates_mirror ON release_first_release_date; DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON release_group; DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON release_group_meta; +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON release_group_primary_type; +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON release_group_secondary_type; DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON release_group_secondary_type_join; DROP TRIGGER IF EXISTS apply_artist_release_pending_updates_mirror ON release_label; DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON track; diff --git a/mbslave/sql/DropPrimaryKeys.sql b/mbslave/sql/DropPrimaryKeys.sql index b16b198..0edea17 100644 --- a/mbslave/sql/DropPrimaryKeys.sql +++ b/mbslave/sql/DropPrimaryKeys.sql @@ -264,6 +264,7 @@ ALTER TABLE medium_attribute_type_allowed_value DROP CONSTRAINT IF EXISTS medium ALTER TABLE medium_attribute_type_allowed_value_allowed_format DROP CONSTRAINT IF EXISTS medium_attribute_type_allowed_value_allowed_format_pkey; ALTER TABLE medium_cdtoc DROP CONSTRAINT IF EXISTS medium_cdtoc_pkey; ALTER TABLE medium_format DROP CONSTRAINT IF EXISTS medium_format_pkey; +ALTER TABLE medium_gid_redirect DROP CONSTRAINT IF EXISTS medium_gid_redirect_pkey; ALTER TABLE medium_index DROP CONSTRAINT IF EXISTS medium_index_pkey; ALTER TABLE mood DROP CONSTRAINT IF EXISTS mood_pkey; ALTER TABLE mood_alias DROP CONSTRAINT IF EXISTS mood_alias_pkey; diff --git a/mbslave/sql/DropReplicationTriggers.sql b/mbslave/sql/DropReplicationTriggers.sql index 1a48ba5..4c1fa3e 100644 --- a/mbslave/sql/DropReplicationTriggers.sql +++ b/mbslave/sql/DropReplicationTriggers.sql @@ -204,6 +204,7 @@ DROP TRIGGER IF EXISTS reptg_medium_attribute_type_allowed_value ON medium_attri DROP TRIGGER IF EXISTS reptg_medium_attribute_type_allowed_value_allowed_format ON medium_attribute_type_allowed_value_allowed_format; DROP TRIGGER IF EXISTS reptg_medium_cdtoc ON medium_cdtoc; DROP TRIGGER IF EXISTS reptg_medium_format ON medium_format; +DROP TRIGGER IF EXISTS reptg_medium_gid_redirect ON medium_gid_redirect; DROP TRIGGER IF EXISTS reptg_medium_index ON medium_index; DROP TRIGGER IF EXISTS reptg_mood ON mood; DROP TRIGGER IF EXISTS reptg_mood_alias ON mood_alias; diff --git a/mbslave/sql/DropReplicationTriggers2.sql b/mbslave/sql/DropReplicationTriggers2.sql index 7474e75..ed646bf 100644 --- a/mbslave/sql/DropReplicationTriggers2.sql +++ b/mbslave/sql/DropReplicationTriggers2.sql @@ -204,6 +204,7 @@ DROP TRIGGER IF EXISTS reptg2_medium_attribute_type_allowed_value ON medium_attr DROP TRIGGER IF EXISTS reptg2_medium_attribute_type_allowed_value_allowed_format ON medium_attribute_type_allowed_value_allowed_format; DROP TRIGGER IF EXISTS reptg2_medium_cdtoc ON medium_cdtoc; DROP TRIGGER IF EXISTS reptg2_medium_format ON medium_format; +DROP TRIGGER IF EXISTS reptg2_medium_gid_redirect ON medium_gid_redirect; DROP TRIGGER IF EXISTS reptg2_medium_index ON medium_index; DROP TRIGGER IF EXISTS reptg2_mood ON mood; DROP TRIGGER IF EXISTS reptg2_mood_alias ON mood_alias; diff --git a/mbslave/sql/DropTables.sql b/mbslave/sql/DropTables.sql index 8eb5357..6d1e53e 100644 --- a/mbslave/sql/DropTables.sql +++ b/mbslave/sql/DropTables.sql @@ -268,6 +268,7 @@ DROP TABLE medium_attribute_type_allowed_value; DROP TABLE medium_attribute_type_allowed_value_allowed_format; DROP TABLE medium_cdtoc; DROP TABLE medium_format; +DROP TABLE medium_gid_redirect; DROP TABLE medium_index; DROP TABLE mood; DROP TABLE mood_alias; diff --git a/mbslave/sql/DropTriggers.sql b/mbslave/sql/DropTriggers.sql index 17e54e9..063dab1 100644 --- a/mbslave/sql/DropTriggers.sql +++ b/mbslave/sql/DropTriggers.sql @@ -194,6 +194,8 @@ DROP TRIGGER IF EXISTS a_ins_release_group ON release_group; DROP TRIGGER IF EXISTS a_upd_release_group ON release_group; DROP TRIGGER IF EXISTS a_del_release_group ON release_group; DROP TRIGGER IF EXISTS b_upd_release_group ON release_group; +DROP TRIGGER IF EXISTS a_upd_release_group_primary_type ON release_group_primary_type; +DROP TRIGGER IF EXISTS a_upd_release_group_secondary_type ON release_group_secondary_type; DROP TRIGGER IF EXISTS a_ins_release_group_secondary_type_join ON release_group_secondary_type_join; DROP TRIGGER IF EXISTS a_del_release_group_secondary_type_join ON release_group_secondary_type_join; DROP TRIGGER IF EXISTS b_upd_release_group_secondary_type_join ON release_group_secondary_type_join; @@ -386,6 +388,8 @@ DROP TRIGGER IF EXISTS apply_artist_release_pending_updates ON release_country; DROP TRIGGER IF EXISTS apply_artist_release_pending_updates ON release_first_release_date; DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON release_group; DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON release_group_meta; +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON release_group_primary_type; +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON release_group_secondary_type; DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON release_group_secondary_type_join; DROP TRIGGER IF EXISTS apply_artist_release_pending_updates ON release_label; DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON track; diff --git a/mbslave/sql/EnableLastUpdatedTriggers.sql b/mbslave/sql/EnableLastUpdatedTriggers.sql old mode 100755 new mode 100644 diff --git a/mbslave/sql/InsertTestData.sql b/mbslave/sql/InsertTestData.sql index 0fecd6c..8914845 100644 --- a/mbslave/sql/InsertTestData.sql +++ b/mbslave/sql/InsertTestData.sql @@ -110,8 +110,8 @@ INSERT INTO release_label (id, release, label, catalog_number) INSERT INTO url (id, gid, url) VALUES (1, '9201840b-d810-4e0f-bb75-c791205f5b24', 'http://musicbrainz.org/'); -INSERT INTO medium (id, release, position, format, name) VALUES (1, 1, 1, 1, 'The First Disc'); -INSERT INTO medium (id, release, position, format, name) VALUES (2, 1, 2, 1, 'The Second Disc'); +INSERT INTO medium (id, gid, release, position, format, name) VALUES (1, 'e67d7889-d617-478f-acc2-40012aec59f5', 1, 1, 1, 'The First Disc'); +INSERT INTO medium (id, gid, release, position, format, name) VALUES (2, 'e692e77f-8670-4c1c-b880-8c3d23d14f04', 1, 2, 1, 'The Second Disc'); INSERT INTO track (id, gid, recording, medium, position, number, name, artist_credit, length) VALUES (1, '3fd2523e-1ced-4f83-8b93-c7ecf6960b32', 1, 1, 1, 1, 1, 2, 123456); @@ -157,11 +157,11 @@ INSERT INTO release_label (id, release, label, catalog_number) INSERT INTO release_label (id, release, label, catalog_number) VALUES (4, 3, 2, '82796 97772 2'); -INSERT INTO medium (id, release, position, format, name) VALUES (3, 2, 1, 1, 'A Sea of Honey'); -INSERT INTO medium (id, release, position, format, name) VALUES (4, 2, 2, 1, 'A Sky of Honey'); +INSERT INTO medium (id, gid, release, position, format, name) VALUES (3, '6ff40540-7c91-4d0d-bbdd-a199edb45e08', 2, 1, 1, 'A Sea of Honey'); +INSERT INTO medium (id, gid, release, position, format, name) VALUES (4, '76e93539-2c4a-4e24-b3ad-79657cb8185e', 2, 2, 1, 'A Sky of Honey'); -INSERT INTO medium (id, release, position, format, name) VALUES (5, 3, 1, 1, 'A Sea of Honey'); -INSERT INTO medium (id, release, position, format, name) VALUES (6, 3, 2, 1, 'A Sky of Honey'); +INSERT INTO medium (id, gid, release, position, format, name) VALUES (5, '84130ff4-50bb-45cf-a3db-454236a59bc4', 3, 1, 1, 'A Sea of Honey'); +INSERT INTO medium (id, gid, release, position, format, name) VALUES (6, '0e8c3742-21be-48ec-8672-138cd0e6d178', 3, 2, 1, 'A Sky of Honey'); INSERT INTO recording (id, gid, name, artist_credit, length, last_updated) VALUES (2, '54b9d183-7dab-42ba-94a3-7388a66604b8', 'King of the Mountain', 3, 293720, '2020-02-20 19:00:00'); @@ -242,6 +242,7 @@ INSERT INTO isrc (isrc, recording) VALUES ('DEE250800230', 2); INSERT INTO link (id, link_type, attribute_count) VALUES (1, 148, 1); INSERT INTO link (id, link_type, attribute_count) VALUES (2, 148, 2); INSERT INTO link (id, link_type, attribute_count, begin_date_year) VALUES (3, 183, 0, 2006); +INSERT INTO link (id, link_type, attribute_count) VALUES (4, 108, 0); INSERT INTO link_attribute (link, attribute_type) VALUES (1, 229); INSERT INTO link_attribute (link, attribute_type) VALUES (2, 1); @@ -256,6 +257,7 @@ INSERT INTO artist (id, gid, name, sort_name, comment) VALUES INSERT INTO event (id, gid, name, begin_date_year, begin_date_month, begin_date_day, end_date_year, end_date_month, end_date_day, time, type, cancelled, setlist, comment, ended) VALUES (59357, 'ca1d24c1-1999-46fd-8a95-3d4108df5cb2', 'BBC Open Music Prom', 2022, 9, 1, 2022, 9, 1, '19:30:00', 1, 'f', NULL, '2022, Prom 60', 't'); +INSERT INTO l_artist_artist (id, link, entity0, entity1) VALUES (1, 4, 8, 9); INSERT INTO l_artist_recording (id, link, entity0, entity1) VALUES (1, 1, 8, 2); INSERT INTO l_artist_recording (id, link, entity0, entity1, edits_pending) VALUES (2, 1, 9, 2, 1); INSERT INTO l_artist_recording (id, link, entity0, entity1) VALUES (3, 2, 8, 3); diff --git a/mbslave/sql/TruncateTables.sql b/mbslave/sql/TruncateTables.sql index db1e112..a9daad7 100644 --- a/mbslave/sql/TruncateTables.sql +++ b/mbslave/sql/TruncateTables.sql @@ -268,6 +268,7 @@ TRUNCATE TABLE medium_attribute_type_allowed_value RESTART IDENTITY CASCADE; TRUNCATE TABLE medium_attribute_type_allowed_value_allowed_format RESTART IDENTITY CASCADE; TRUNCATE TABLE medium_cdtoc RESTART IDENTITY CASCADE; TRUNCATE TABLE medium_format RESTART IDENTITY CASCADE; +TRUNCATE TABLE medium_gid_redirect RESTART IDENTITY CASCADE; TRUNCATE TABLE medium_index RESTART IDENTITY CASCADE; TRUNCATE TABLE mood RESTART IDENTITY CASCADE; TRUNCATE TABLE mood_alias RESTART IDENTITY CASCADE; diff --git a/mbslave/sql/caa/CreateMQTriggers.sql b/mbslave/sql/caa/CreateMQTriggers.sql deleted file mode 100644 index b508800..0000000 --- a/mbslave/sql/caa/CreateMQTriggers.sql +++ /dev/null @@ -1,148 +0,0 @@ -BEGIN; - -SET search_path = 'cover_art_archive'; - -CREATE OR REPLACE FUNCTION reindex_release() RETURNS trigger AS $$ - DECLARE - release_mbid UUID; - BEGIN - SELECT gid INTO release_mbid - FROM musicbrainz.release r - JOIN cover_art_archive.cover_art caa_r ON r.id = caa_r.release - WHERE r.id = NEW.id; - - IF FOUND THEN - PERFORM amqp.publish(1, 'cover-art-archive', 'index', release_mbid::text); - END IF; - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER caa_reindex AFTER UPDATE OR INSERT -ON musicbrainz.release FOR EACH ROW -EXECUTE PROCEDURE reindex_release(); - -CREATE OR REPLACE FUNCTION reindex_artist() RETURNS trigger AS $$ - BEGIN - -- Short circuit if the name hasn't changed - IF NEW.name = OLD.name AND NEW.sort_name = OLD.sort_name THEN - RETURN NULL; - END IF; - - PERFORM amqp.publish(1, 'cover-art-archive', 'index', r.gid::text) - FROM musicbrainz.release r - JOIN cover_art_archive.cover_art caa_r ON r.id = caa_r.release - JOIN musicbrainz.artist_credit_name acn ON r.artist_credit = acn.artist_credit - WHERE acn.artist = NEW.id; - - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER caa_reindex AFTER UPDATE -ON musicbrainz.artist FOR EACH ROW -EXECUTE PROCEDURE reindex_artist(); - -CREATE OR REPLACE FUNCTION reindex_release_via_catno() RETURNS trigger AS $$ - DECLARE - release_mbid UUID; - BEGIN - SELECT gid INTO release_mbid - FROM musicbrainz.release - JOIN musicbrainz.release_label ON release_label.release = release.id - JOIN cover_art_archive.cover_art caa_r ON release.id = caa_r.release - WHERE release.id = NEW.release; - - IF FOUND THEN - PERFORM amqp.publish(1, 'cover-art-archive', 'index', release_mbid::text); - END IF; - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER caa_reindex AFTER UPDATE OR INSERT -ON musicbrainz.release_label FOR EACH ROW -EXECUTE PROCEDURE reindex_release_via_catno(); - -CREATE OR REPLACE FUNCTION reindex_caa() RETURNS trigger AS $$ - BEGIN - PERFORM amqp.publish(1, 'cover-art-archive', 'index', gid::text) - FROM musicbrainz.release - WHERE id = coalesce(( - CASE TG_OP - WHEN 'DELETE' THEN OLD.release - ELSE NEW.release - END)); - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER caa_reindex AFTER UPDATE OR INSERT OR DELETE -ON cover_art_archive.cover_art FOR EACH ROW -EXECUTE PROCEDURE reindex_caa(); - -CREATE OR REPLACE FUNCTION reindex_caa_type() RETURNS trigger AS $$ - BEGIN - PERFORM amqp.publish(1, 'cover-art-archive', 'index', r.gid::text) - FROM musicbrainz.release r - JOIN cover_art_archive.cover_art ca ON r.id = ca.release - WHERE ca.id = coalesce(( - CASE TG_OP - WHEN 'DELETE' THEN OLD.id - ELSE NEW.id - END)); - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER caa_reindex AFTER UPDATE OR INSERT OR DELETE -ON cover_art_archive.cover_art_type FOR EACH ROW -EXECUTE PROCEDURE reindex_caa_type(); - -CREATE OR REPLACE FUNCTION caa_move() RETURNS trigger AS $$ - BEGIN - IF OLD.release != NEW.release THEN - PERFORM amqp.publish(1, 'cover-art-archive', 'move', - (SELECT ca.id || E'\n' || - old_release.gid || E'\n' || - new_release.gid || E'\n' || - it.suffix || E'\n' - FROM cover_art_archive.cover_art ca - JOIN cover_art_archive.image_type it ON it.mime_type = ca.mime_type, - musicbrainz.release old_release, - musicbrainz.release new_release - WHERE ca.id = OLD.id - AND old_release.id = OLD.release - AND new_release.id = NEW.release)); - END IF; - RETURN NEW; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER caa_move BEFORE UPDATE -ON cover_art_archive.cover_art FOR EACH ROW -EXECUTE PROCEDURE caa_move(); - -CREATE OR REPLACE FUNCTION delete_release() RETURNS trigger AS $$ - BEGIN - PERFORM - amqp.publish(1, 'cover-art-archive', 'delete', - (cover_art.id || E'\n' || OLD.gid || E'\n' || image_type.suffix)::text) - FROM cover_art_archive.cover_art - JOIN cover_art_archive.image_type ON image_type.mime_type = cover_art.mime_type - WHERE release = OLD.id; - - PERFORM amqp.publish(1, 'cover-art-archive', 'delete', - ('index.json' || E'\n' || OLD.gid)::text) - FROM musicbrainz.release - WHERE release.id = OLD.id; - - RETURN OLD; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER caa_delete BEFORE DELETE -ON musicbrainz.release FOR EACH ROW -EXECUTE PROCEDURE delete_release(); - -COMMIT; diff --git a/mbslave/sql/caa/CreateViews.sql b/mbslave/sql/caa/CreateViews.sql index c9cbac3..e005e2c 100644 --- a/mbslave/sql/caa/CreateViews.sql +++ b/mbslave/sql/caa/CreateViews.sql @@ -11,7 +11,6 @@ SELECT cover_art.*, JOIN cover_art_archive.cover_art ca_front USING (id) WHERE ca_front.release = cover_art.release AND type_id = 1 - AND mime_type != 'application/pdf' ORDER BY ca_front.ordering LIMIT 1), FALSE) AS is_front, coalesce(cover_art.id = (SELECT id FROM cover_art_archive.cover_art_type diff --git a/mbslave/sql/caa/DropMQTriggers.sql b/mbslave/sql/caa/DropMQTriggers.sql deleted file mode 100644 index b6449b2..0000000 --- a/mbslave/sql/caa/DropMQTriggers.sql +++ /dev/null @@ -1,19 +0,0 @@ -BEGIN; - -DROP TRIGGER caa_reindex ON musicbrainz.artist; -DROP TRIGGER caa_reindex ON musicbrainz.release; -DROP TRIGGER caa_reindex ON musicbrainz.release_label; -DROP TRIGGER caa_reindex ON cover_art_archive.cover_art; -DROP TRIGGER caa_reindex ON cover_art_archive.cover_art_type; -DROP TRIGGER caa_move ON cover_art_archive.cover_art; -DROP TRIGGER caa_delete ON musicbrainz.release; - -DROP FUNCTION cover_art_archive.reindex_release (); -DROP FUNCTION cover_art_archive.reindex_artist (); -DROP FUNCTION cover_art_archive.reindex_release_via_catno (); -DROP FUNCTION cover_art_archive.reindex_caa (); -DROP FUNCTION cover_art_archive.reindex_caa_type (); -DROP FUNCTION cover_art_archive.caa_move (); -DROP FUNCTION cover_art_archive.delete_release (); - -COMMIT; diff --git a/mbslave/sql/eaa/CreateMQTriggers.sql b/mbslave/sql/eaa/CreateMQTriggers.sql deleted file mode 100644 index 4aee8d7..0000000 --- a/mbslave/sql/eaa/CreateMQTriggers.sql +++ /dev/null @@ -1,161 +0,0 @@ -BEGIN; - -SET search_path = 'event_art_archive'; - -CREATE OR REPLACE FUNCTION reindex_event() RETURNS trigger AS $$ - DECLARE - event_mbid UUID; - BEGIN - SELECT gid INTO event_mbid - FROM musicbrainz.event e - JOIN event_art_archive.event_art ea ON e.id = ea.event - WHERE e.id = NEW.id; - - IF FOUND THEN - PERFORM amqp.publish(1, 'event-art-archive', 'index', event_mbid::text); - END IF; - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER eaa_reindex AFTER UPDATE OR INSERT -ON musicbrainz.event FOR EACH ROW -EXECUTE PROCEDURE reindex_event(); - -CREATE OR REPLACE FUNCTION reindex_artist() RETURNS trigger AS $$ - BEGIN - -- Short circuit if the name hasn't changed - IF NEW.name = OLD.name AND NEW.sort_name = OLD.sort_name THEN - RETURN NULL; - END IF; - - PERFORM amqp.publish(1, 'event-art-archive', 'index', e.gid::text) - FROM musicbrainz.event e - JOIN event_art_archive.event_art ea ON e.id = ea.event - JOIN musicbrainz.l_artist_event lae ON e.id = lae.entity1 - WHERE lae.entity0 = NEW.id; - - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER eaa_reindex AFTER UPDATE -ON musicbrainz.artist FOR EACH ROW -EXECUTE PROCEDURE reindex_artist(); - -CREATE OR REPLACE FUNCTION reindex_l_artist_event() RETURNS trigger AS $$ - BEGIN - PERFORM amqp.publish(1, 'event-art-archive', 'index', e.gid::text) - FROM musicbrainz.event e - JOIN event_art_archive.event_art ea ON e.id = ea.event - JOIN musicbrainz.l_artist_event lae ON e.id = lae.entity1 - WHERE lae.id = (CASE TG_OP - WHEN 'DELETE' THEN OLD.id - ELSE NEW.id - END); - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER eaa_reindex AFTER UPDATE OR INSERT OR DELETE -ON musicbrainz.l_artist_event FOR EACH ROW -EXECUTE PROCEDURE reindex_l_artist_event(); - -CREATE OR REPLACE FUNCTION reindex_place() RETURNS trigger AS $$ - BEGIN - PERFORM amqp.publish(1, 'event-art-archive', 'index', e.gid::text) - FROM musicbrainz.event e - JOIN event_art_archive.event_art ea ON e.id = ea.event - JOIN musicbrainz.l_event_place lep ON e.id = lep.entity0 - WHERE lep.entity1 = NEW.id; - - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER eaa_reindex AFTER UPDATE -ON musicbrainz.place FOR EACH ROW -EXECUTE PROCEDURE reindex_place(); - -CREATE OR REPLACE FUNCTION reindex_l_event_place() RETURNS trigger AS $$ - BEGIN - PERFORM amqp.publish(1, 'event-art-archive', 'index', e.gid::text) - FROM musicbrainz.event e - JOIN event_art_archive.event_art ea ON e.id = ea.event - JOIN musicbrainz.l_event_place lep ON e.id = lep.entity0 - WHERE lep.id = (CASE TG_OP - WHEN 'DELETE' THEN OLD.id - ELSE NEW.id - END); - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER eaa_reindex AFTER UPDATE OR INSERT OR DELETE -ON musicbrainz.l_event_place FOR EACH ROW -EXECUTE PROCEDURE reindex_l_event_place(); - -CREATE OR REPLACE FUNCTION reindex_eaa() RETURNS trigger AS $$ - BEGIN - PERFORM amqp.publish(1, 'event-art-archive', 'index', gid::text) - FROM musicbrainz.event - WHERE id = coalesce(( - CASE TG_OP - WHEN 'DELETE' THEN OLD.event - ELSE NEW.event - END)); - RETURN NULL; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER eaa_reindex AFTER UPDATE OR INSERT OR DELETE -ON event_art_archive.event_art FOR EACH ROW -EXECUTE PROCEDURE reindex_eaa(); - -CREATE OR REPLACE FUNCTION move_event() RETURNS trigger AS $$ - BEGIN - IF OLD.event != NEW.event THEN - PERFORM amqp.publish(1, 'event-art-archive', 'move', - (SELECT ea.id || E'\n' || - old_event.gid || E'\n' || - new_event.gid || E'\n' || - it.suffix || E'\n' - FROM event_art_archive.event_art ea - JOIN cover_art_archive.image_type it ON it.mime_type = ea.mime_type, - musicbrainz.event old_event, - musicbrainz.event new_event - WHERE ea.id = OLD.id - AND old_event.id = OLD.event - AND new_event.id = NEW.event)); - END IF; - RETURN NEW; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER eaa_move BEFORE UPDATE -ON event_art_archive.event_art FOR EACH ROW -EXECUTE PROCEDURE move_event(); - -CREATE OR REPLACE FUNCTION delete_event() RETURNS trigger AS $$ - BEGIN - PERFORM - amqp.publish(1, 'event-art-archive', 'delete', - (event_art.id || E'\n' || OLD.gid || E'\n' || image_type.suffix)::text) - FROM event_art_archive.event_art - JOIN cover_art_archive.image_type ON image_type.mime_type = event_art.mime_type - WHERE event = OLD.id; - - PERFORM amqp.publish(1, 'event-art-archive', 'delete', - ('index.json' || E'\n' || OLD.gid)::text) - FROM musicbrainz.event - WHERE event.id = OLD.id; - - RETURN OLD; - END; -$$ LANGUAGE 'plpgsql'; - -CREATE TRIGGER eaa_delete BEFORE DELETE -ON musicbrainz.event FOR EACH ROW -EXECUTE PROCEDURE delete_event(); - -COMMIT; diff --git a/mbslave/sql/eaa/CreateViews.sql b/mbslave/sql/eaa/CreateViews.sql index 56f9aaa..cb87fc4 100644 --- a/mbslave/sql/eaa/CreateViews.sql +++ b/mbslave/sql/eaa/CreateViews.sql @@ -11,7 +11,6 @@ SELECT event_art.*, JOIN event_art_archive.event_art ea_front USING (id) WHERE ea_front.event = event_art.event AND type_id = 1 - AND mime_type != 'application/pdf' ORDER BY ea_front.ordering LIMIT 1), FALSE) AS is_front, array(SELECT art_type.name diff --git a/mbslave/sql/eaa/DropMQTriggers.sql b/mbslave/sql/eaa/DropMQTriggers.sql deleted file mode 100644 index 3651e68..0000000 --- a/mbslave/sql/eaa/DropMQTriggers.sql +++ /dev/null @@ -1,21 +0,0 @@ -BEGIN; - -DROP TRIGGER eaa_delete ON musicbrainz.event; -DROP TRIGGER eaa_move ON event_art_archive.event_art; -DROP TRIGGER eaa_reindex ON event_art_archive.event_art; -DROP TRIGGER eaa_reindex ON musicbrainz.artist; -DROP TRIGGER eaa_reindex ON musicbrainz.event; -DROP TRIGGER eaa_reindex ON musicbrainz.l_artist_event; -DROP TRIGGER eaa_reindex ON musicbrainz.l_event_place; -DROP TRIGGER eaa_reindex ON musicbrainz.place; - -DROP FUNCTION event_art_archive.delete_event (); -DROP FUNCTION event_art_archive.move_event (); -DROP FUNCTION event_art_archive.reindex_artist (); -DROP FUNCTION event_art_archive.reindex_eaa (); -DROP FUNCTION event_art_archive.reindex_event (); -DROP FUNCTION event_art_archive.reindex_l_artist_event (); -DROP FUNCTION event_art_archive.reindex_l_event_place (); -DROP FUNCTION event_art_archive.reindex_place (); - -COMMIT; diff --git a/mbslave/sql/updates/20240221-mbs-13492.sql b/mbslave/sql/updates/20240221-mbs-13492.sql new file mode 100644 index 0000000..6cc4950 --- /dev/null +++ b/mbslave/sql/updates/20240221-mbs-13492.sql @@ -0,0 +1,23 @@ +\set ON_ERROR_STOP 1 + +BEGIN; +SET LOCAL statement_timeout = 0; + +UPDATE editor + SET privs = privs | 8192 -- set new beginner flag + WHERE id != 4 -- avoid setting ModBot as beginner + AND NOT deleted + AND ( + member_since > NOW() - INTERVAL '2 weeks' + OR + NOT EXISTS ( + SELECT 1 + FROM edit + WHERE edit.editor = editor.id + AND edit.autoedit = 0 + AND edit.status = 2 + OFFSET 9 + ) + ); + +COMMIT; diff --git a/mbslave/sql/updates/20240726-mbs-9373.sql b/mbslave/sql/updates/20240726-mbs-9373.sql new file mode 100644 index 0000000..96c5ce1 --- /dev/null +++ b/mbslave/sql/updates/20240726-mbs-9373.sql @@ -0,0 +1,9 @@ +\set ON_ERROR_STOP 1 + +BEGIN; + +UPDATE editor + SET privs = privs | 16384 -- set new voting disabled flag + WHERE (privs & 1024) > 0; -- where editor had editing disabled flag + +COMMIT; diff --git a/mbslave/sql/updates/20241017-mbs-9253-13464.sql b/mbslave/sql/updates/20241017-mbs-9253-13464.sql new file mode 100644 index 0000000..b7af8c9 --- /dev/null +++ b/mbslave/sql/updates/20241017-mbs-9253-13464.sql @@ -0,0 +1,136 @@ +\set ON_ERROR_STOP 1 + +BEGIN; + +DROP TRIGGER IF EXISTS a_upd_release_group_primary_type ON release_group_primary_type; +DROP TRIGGER IF EXISTS a_upd_release_group_secondary_type ON release_group_secondary_type; + +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON release_group_primary_type; +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON release_group_secondary_type; + +DROP FUNCTION get_artist_release_group_rows(integer); + +DROP INDEX artist_release_group_nonva_idx_sort; +DROP INDEX artist_release_group_va_idx_sort; + +DROP TABLE artist_release_group_nonva; +DROP TABLE artist_release_group_va; +DROP TABLE artist_release_group; + +CREATE TABLE artist_release_group ( + -- See comment for `artist_release.is_track_artist`. + is_track_artist BOOLEAN NOT NULL, + artist INTEGER NOT NULL, -- references artist.id, CASCADE + unofficial BOOLEAN NOT NULL, + primary_type_child_order SMALLINT, + primary_type SMALLINT, + secondary_type_child_orders SMALLINT[], + secondary_types SMALLINT[], + first_release_date INTEGER, + name VARCHAR COLLATE musicbrainz NOT NULL, + release_group INTEGER NOT NULL -- references release_group.id, CASCADE +) PARTITION BY LIST (is_track_artist); + +CREATE TABLE artist_release_group_nonva + PARTITION OF artist_release_group FOR VALUES IN (FALSE); + +CREATE TABLE artist_release_group_va + PARTITION OF artist_release_group FOR VALUES IN (TRUE); + +CREATE OR REPLACE FUNCTION get_artist_release_group_rows( + release_group_id INTEGER +) RETURNS SETOF artist_release_group AS $$ +BEGIN + -- PostgreSQL 12 generates a vastly more efficient plan when only + -- one release group ID is passed. A condition like + -- `rg.id = any(...)` can be over 200x slower, even with only one + -- release group ID in the array. + RETURN QUERY EXECUTE $SQL$ + SELECT DISTINCT ON (a_rg.artist, rg.id) + a_rg.is_track_artist, + a_rg.artist, + -- Withdrawn releases were once official by definition + bool_and(r.status IS NOT NULL AND r.status != 1 AND r.status != 5), + rgpt.child_order::SMALLINT, + rg.type::SMALLINT, + array_agg( + DISTINCT rgst.child_order ORDER BY rgst.child_order) + FILTER (WHERE rgst.child_order IS NOT NULL + )::SMALLINT[], + array_agg( + DISTINCT st.secondary_type ORDER BY st.secondary_type) + FILTER (WHERE st.secondary_type IS NOT NULL + )::SMALLINT[], + integer_date( + rgm.first_release_date_year, + rgm.first_release_date_month, + rgm.first_release_date_day + ), + rg.name, + rg.id + FROM ( + SELECT FALSE AS is_track_artist, rgacn.artist, rg.id AS release_group + FROM release_group rg + JOIN artist_credit_name rgacn ON rgacn.artist_credit = rg.artist_credit + UNION ALL + SELECT TRUE AS is_track_artist, tacn.artist, r.release_group + FROM release r + JOIN medium m ON m.release = r.id + JOIN track t ON t.medium = m.id + JOIN artist_credit_name tacn ON tacn.artist_credit = t.artist_credit + ) a_rg + JOIN release_group rg ON rg.id = a_rg.release_group + LEFT JOIN release r ON r.release_group = rg.id + JOIN release_group_meta rgm ON rgm.id = rg.id + LEFT JOIN release_group_primary_type rgpt ON rgpt.id = rg.type + LEFT JOIN release_group_secondary_type_join st ON st.release_group = rg.id + LEFT JOIN release_group_secondary_type rgst ON rgst.id = st.secondary_type + $SQL$ || (CASE WHEN release_group_id IS NULL THEN '' ELSE 'WHERE rg.id = $1' END) || + $SQL$ + GROUP BY a_rg.is_track_artist, a_rg.artist, rgm.id, rg.id, rgpt.child_order + ORDER BY a_rg.artist, rg.id, a_rg.is_track_artist + $SQL$ + USING release_group_id; +END; +$$ LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION a_upd_release_group_primary_type_mirror() +RETURNS trigger AS $$ +BEGIN + -- DO NOT modify any replicated tables in this function; it's used + -- by a trigger on mirrors. + IF (NEW.child_order IS DISTINCT FROM OLD.child_order) + THEN + INSERT INTO artist_release_group_pending_update ( + SELECT id FROM release_group + WHERE release_group.type = OLD.id + ); + END IF; + RETURN NULL; +END; +$$ LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION a_upd_release_group_secondary_type_mirror() +RETURNS trigger AS $$ +BEGIN + -- DO NOT modify any replicated tables in this function; it's used + -- by a trigger on mirrors. + IF (NEW.child_order IS DISTINCT FROM OLD.child_order) + THEN + INSERT INTO artist_release_group_pending_update ( + SELECT release_group + FROM release_group_secondary_type_join + WHERE secondary_type = OLD.id + ); + END IF; + RETURN NULL; +END; +$$ LANGUAGE 'plpgsql'; + +CREATE INDEX artist_release_group_nonva_idx_sort ON artist_release_group_nonva (artist, unofficial, primary_type_child_order NULLS FIRST, primary_type NULLS FIRST, secondary_type_child_orders NULLS FIRST, secondary_types NULLS FIRST, first_release_date NULLS LAST, name, release_group); +CREATE INDEX artist_release_group_va_idx_sort ON artist_release_group_va (artist, unofficial, primary_type_child_order NULLS FIRST, primary_type NULLS FIRST, secondary_type_child_orders NULLS FIRST, secondary_types NULLS FIRST, first_release_date NULLS LAST, name, release_group); + +CREATE UNIQUE INDEX artist_release_group_nonva_idx_uniq ON artist_release_group_nonva (release_group, artist); +CREATE UNIQUE INDEX artist_release_group_va_idx_uniq ON artist_release_group_va (release_group, artist); + +COMMIT; diff --git a/mbslave/sql/updates/20241017-mbs-9253-master_and_standalone.sql b/mbslave/sql/updates/20241017-mbs-9253-master_and_standalone.sql new file mode 100644 index 0000000..dcaa5f3 --- /dev/null +++ b/mbslave/sql/updates/20241017-mbs-9253-master_and_standalone.sql @@ -0,0 +1,37 @@ +\set ON_ERROR_STOP 1 + +SET search_path = musicbrainz; + +BEGIN; + +ALTER TABLE artist_release_group + ADD CONSTRAINT artist_release_group_fk_artist + FOREIGN KEY (artist) + REFERENCES artist(id) + ON DELETE CASCADE; + +ALTER TABLE artist_release_group + ADD CONSTRAINT artist_release_group_fk_release_group + FOREIGN KEY (release_group) + REFERENCES release_group(id) + ON DELETE CASCADE; + +CREATE TRIGGER a_upd_release_group_primary_type AFTER UPDATE ON release_group_primary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_primary_type_mirror(); + +CREATE TRIGGER a_upd_release_group_secondary_type AFTER UPDATE ON release_group_secondary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_secondary_type_mirror(); + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates + AFTER UPDATE ON release_group_primary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates + AFTER UPDATE ON release_group_secondary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +COMMIT; diff --git a/mbslave/sql/updates/20241017-mbs-9253-mirror_only.sql b/mbslave/sql/updates/20241017-mbs-9253-mirror_only.sql new file mode 100644 index 0000000..e42e50d --- /dev/null +++ b/mbslave/sql/updates/20241017-mbs-9253-mirror_only.sql @@ -0,0 +1,31 @@ +\set ON_ERROR_STOP 1 + +BEGIN; + +DROP TRIGGER IF EXISTS a_upd_release_group_primary_type_mirror ON release_group_primary_type; + +CREATE TRIGGER a_upd_release_group_primary_type_mirror AFTER UPDATE ON release_group_primary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_primary_type_mirror(); + +DROP TRIGGER IF EXISTS a_upd_release_group_secondary_type_mirror ON release_group_secondary_type; + +CREATE TRIGGER a_upd_release_group_secondary_type_mirror AFTER UPDATE ON release_group_secondary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_secondary_type_mirror(); + +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON release_group_primary_type; + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates_mirror + AFTER UPDATE ON release_group_primary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON release_group_secondary_type; + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates_mirror + AFTER UPDATE ON release_group_secondary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +COMMIT; diff --git a/mbslave/sql/updates/20241125-mbs-13832.sql b/mbslave/sql/updates/20241125-mbs-13832.sql new file mode 100644 index 0000000..5a7e1de --- /dev/null +++ b/mbslave/sql/updates/20241125-mbs-13832.sql @@ -0,0 +1,48 @@ +\set ON_ERROR_STOP 1 + +BEGIN; + +-- MBS-14014 +DROP VIEW IF EXISTS cover_art_archive.index_listing; + +-- CAA view +CREATE VIEW cover_art_archive.index_listing AS +SELECT cover_art.*, + (edit.close_time IS NOT NULL) AS approved, + coalesce(cover_art.id = (SELECT id FROM cover_art_archive.cover_art_type + JOIN cover_art_archive.cover_art ca_front USING (id) + WHERE ca_front.release = cover_art.release + AND type_id = 1 + ORDER BY ca_front.ordering + LIMIT 1), FALSE) AS is_front, + coalesce(cover_art.id = (SELECT id FROM cover_art_archive.cover_art_type + JOIN cover_art_archive.cover_art ca_front USING (id) + WHERE ca_front.release = cover_art.release + AND type_id = 2 + ORDER BY ca_front.ordering + LIMIT 1), FALSE) AS is_back, + array(SELECT art_type.name + FROM cover_art_archive.cover_art_type + JOIN cover_art_archive.art_type ON cover_art_type.type_id = art_type.id + WHERE cover_art_type.id = cover_art.id) AS types +FROM cover_art_archive.cover_art +LEFT JOIN musicbrainz.edit ON edit.id = cover_art.edit; + +-- EAA view +CREATE OR REPLACE VIEW event_art_archive.index_listing AS +SELECT event_art.*, + (edit.close_time IS NOT NULL) AS approved, + coalesce(event_art.id = (SELECT id FROM event_art_archive.event_art_type + JOIN event_art_archive.event_art ea_front USING (id) + WHERE ea_front.event = event_art.event + AND type_id = 1 + ORDER BY ea_front.ordering + LIMIT 1), FALSE) AS is_front, + array(SELECT art_type.name + FROM event_art_archive.event_art_type + JOIN event_art_archive.art_type ON event_art_type.type_id = art_type.id + WHERE event_art_type.id = event_art.id) AS types +FROM event_art_archive.event_art +LEFT JOIN musicbrainz.edit ON edit.id = event_art.edit; + +COMMIT; diff --git a/mbslave/sql/updates/20250320-mbs-13768-fks.sql b/mbslave/sql/updates/20250320-mbs-13768-fks.sql new file mode 100644 index 0000000..788b9b3 --- /dev/null +++ b/mbslave/sql/updates/20250320-mbs-13768-fks.sql @@ -0,0 +1,12 @@ +\set ON_ERROR_STOP 1 + +SET search_path = musicbrainz; + +BEGIN; + +ALTER TABLE medium_gid_redirect + ADD CONSTRAINT medium_gid_redirect_fk_new_id + FOREIGN KEY (new_id) + REFERENCES medium(id); + +COMMIT; diff --git a/mbslave/sql/updates/20250320-mbs-13768.sql b/mbslave/sql/updates/20250320-mbs-13768.sql new file mode 100644 index 0000000..366593a --- /dev/null +++ b/mbslave/sql/updates/20250320-mbs-13768.sql @@ -0,0 +1,31 @@ +\set ON_ERROR_STOP 1 + +BEGIN; + +-- Medium GID + +-- Creating column +ALTER TABLE medium ADD COLUMN gid uuid; + +-- Generating GIDs +UPDATE medium SET gid = + generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'medium' || id); + +-- Adding NOT NULL constraint +ALTER TABLE medium ALTER COLUMN gid SET NOT NULL; + +-- Creating index +CREATE UNIQUE INDEX medium_idx_gid ON medium (gid); + +-- Medium GID redirect +CREATE TABLE medium_gid_redirect ( -- replicate (verbose) + gid UUID NOT NULL, -- PK + new_id INTEGER NOT NULL, -- references medium.id + created TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + +ALTER TABLE medium_gid_redirect ADD CONSTRAINT medium_gid_redirect_pkey PRIMARY KEY (gid); + +CREATE INDEX medium_gid_redirect_idx_new_id ON medium_gid_redirect (new_id); + +COMMIT; diff --git a/mbslave/sql/updates/20250408-mbs-13322.sql b/mbslave/sql/updates/20250408-mbs-13322.sql new file mode 100644 index 0000000..4ed4b1c --- /dev/null +++ b/mbslave/sql/updates/20250408-mbs-13322.sql @@ -0,0 +1,15 @@ +\set ON_ERROR_STOP 1 + +BEGIN; + +CREATE OR REPLACE FUNCTION delete_unused_url(ids INTEGER[]) +RETURNS VOID AS $$ +BEGIN + DELETE FROM url_gid_redirect WHERE new_id = any(ids); + DELETE FROM url WHERE id = any(ids); +EXCEPTION + WHEN foreign_key_violation THEN RETURN; +END; +$$ LANGUAGE 'plpgsql'; + +COMMIT; diff --git a/mbslave/sql/updates/20250408-mbs-13964-all.sql b/mbslave/sql/updates/20250408-mbs-13964-all.sql new file mode 100644 index 0000000..5b2a77c --- /dev/null +++ b/mbslave/sql/updates/20250408-mbs-13964-all.sql @@ -0,0 +1,34 @@ +\set ON_ERROR_STOP 1 + +BEGIN; + +CREATE OR REPLACE FUNCTION set_mediums_recordings_first_release_dates(medium_ids INTEGER[]) +RETURNS VOID AS $$ +BEGIN + PERFORM set_recordings_first_release_dates(( + SELECT array_agg(recording) + FROM track + WHERE track.medium = any(medium_ids) + )); + RETURN; +END; +$$ LANGUAGE 'plpgsql' STRICT; + +CREATE OR REPLACE FUNCTION a_upd_medium_mirror() +RETURNS trigger AS $$ +BEGIN + -- DO NOT modify any replicated tables in this function; it's used + -- by a trigger on mirrors. + IF NEW.release IS DISTINCT FROM OLD.release THEN + PERFORM set_mediums_recordings_first_release_dates(ARRAY[OLD.id]); + END IF; + RETURN NULL; +END; +$$ LANGUAGE 'plpgsql'; + +CREATE TRIGGER a_upd_medium AFTER UPDATE ON medium + FOR EACH ROW EXECUTE PROCEDURE a_upd_medium_mirror(); + +TRUNCATE recording_first_release_date; + +COMMIT; diff --git a/mbslave/sql/updates/20250425-mbs-13464-master_and_standalone.sql b/mbslave/sql/updates/20250425-mbs-13464-master_and_standalone.sql new file mode 100644 index 0000000..42b4259 --- /dev/null +++ b/mbslave/sql/updates/20250425-mbs-13464-master_and_standalone.sql @@ -0,0 +1,19 @@ +\set ON_ERROR_STOP 1 + +SET search_path = musicbrainz; + +BEGIN; + +ALTER TABLE artist_release + ADD CONSTRAINT artist_release_fk_artist + FOREIGN KEY (artist) + REFERENCES artist(id) + ON DELETE CASCADE; + +ALTER TABLE artist_release + ADD CONSTRAINT artist_release_fk_release + FOREIGN KEY (release) + REFERENCES release(id) + ON DELETE CASCADE; + +COMMIT; diff --git a/mbslave/sql/updates/20250425-mbs-13464.sql b/mbslave/sql/updates/20250425-mbs-13464.sql new file mode 100644 index 0000000..98f596e --- /dev/null +++ b/mbslave/sql/updates/20250425-mbs-13464.sql @@ -0,0 +1,81 @@ +\set ON_ERROR_STOP 1 + +BEGIN; + +DROP FUNCTION get_artist_release_rows(integer); + +DROP TABLE artist_release_nonva; +DROP TABLE artist_release_va; +DROP TABLE artist_release; + +CREATE TABLE artist_release ( + is_track_artist BOOLEAN NOT NULL, + artist INTEGER NOT NULL, + first_release_date INTEGER, + catalog_numbers TEXT[], + country_code CHAR(2), + barcode BIGINT, + name VARCHAR COLLATE musicbrainz NOT NULL, + release INTEGER NOT NULL +) PARTITION BY LIST (is_track_artist); + +CREATE TABLE artist_release_nonva + PARTITION OF artist_release FOR VALUES IN (FALSE); + +CREATE TABLE artist_release_va + PARTITION OF artist_release FOR VALUES IN (TRUE); + +CREATE OR REPLACE FUNCTION get_artist_release_rows( + release_id INTEGER +) RETURNS SETOF artist_release AS $$ +BEGIN + -- PostgreSQL 12 generates a vastly more efficient plan when only + -- one release ID is passed. A condition like `r.id = any(...)` + -- can be over 200x slower, even with only one release ID in the + -- array. + RETURN QUERY EXECUTE $SQL$ + SELECT DISTINCT ON (ar.artist, r.id) + ar.is_track_artist, + ar.artist, + integer_date(rfrd.year, rfrd.month, rfrd.day) AS first_release_date, + array_agg( + DISTINCT rl.catalog_number ORDER BY rl.catalog_number + ) FILTER (WHERE rl.catalog_number IS NOT NULL)::TEXT[] AS catalog_numbers, + min(iso.code ORDER BY iso.code)::CHAR(2) AS country_code, + left(regexp_replace( + (CASE r.barcode WHEN '' THEN '0' ELSE r.barcode END), + '[^0-9]+', '', 'g' + ), 18)::BIGINT AS barcode, + r.name, + r.id + FROM ( + SELECT FALSE AS is_track_artist, racn.artist, r.id AS release + FROM release r + JOIN artist_credit_name racn ON racn.artist_credit = r.artist_credit + UNION ALL + SELECT TRUE AS is_track_artist, tacn.artist, m.release + FROM medium m + JOIN track t ON t.medium = m.id + JOIN artist_credit_name tacn ON tacn.artist_credit = t.artist_credit + ) ar + JOIN release r ON r.id = ar.release + LEFT JOIN release_first_release_date rfrd ON rfrd.release = r.id + LEFT JOIN release_label rl ON rl.release = r.id + LEFT JOIN release_country rc ON rc.release = r.id + LEFT JOIN iso_3166_1 iso ON iso.area = rc.country + $SQL$ || (CASE WHEN release_id IS NULL THEN '' ELSE 'WHERE r.id = $1' END) || + $SQL$ + GROUP BY ar.is_track_artist, ar.artist, rfrd.release, r.id + ORDER BY ar.artist, r.id, ar.is_track_artist + $SQL$ + USING release_id; +END; +$$ LANGUAGE plpgsql; + +CREATE INDEX artist_release_nonva_idx_sort ON artist_release_nonva (artist, first_release_date NULLS LAST, catalog_numbers NULLS LAST, country_code NULLS LAST, barcode NULLS LAST, name, release); +CREATE INDEX artist_release_va_idx_sort ON artist_release_va (artist, first_release_date NULLS LAST, catalog_numbers NULLS LAST, country_code NULLS LAST, barcode NULLS LAST, name, release); + +CREATE UNIQUE INDEX artist_release_nonva_idx_uniq ON artist_release_nonva (release, artist); +CREATE UNIQUE INDEX artist_release_va_idx_uniq ON artist_release_va (release, artist); + +COMMIT; diff --git a/mbslave/sql/updates/20250425-mbs-13966.sql b/mbslave/sql/updates/20250425-mbs-13966.sql new file mode 100644 index 0000000..3792cdb --- /dev/null +++ b/mbslave/sql/updates/20250425-mbs-13966.sql @@ -0,0 +1,50 @@ +\set ON_ERROR_STOP 1 + +BEGIN; + +CREATE OR REPLACE FUNCTION set_release_group_first_release_date(release_group_id INTEGER) +RETURNS VOID AS $$ +BEGIN + UPDATE release_group_meta SET first_release_date_year = first.year, + first_release_date_month = first.month, + first_release_date_day = first.day + FROM ( + SELECT rd.year, rd.month, rd.day + FROM release_group + LEFT JOIN release ON release.release_group = release_group.id + LEFT JOIN release_first_release_date rd ON (rd.release = release.id) + WHERE release_group.id = release_group_id + ORDER BY + rd.year NULLS LAST, + rd.month NULLS LAST, + rd.day NULLS LAST + LIMIT 1 + ) AS first + WHERE id = release_group_id; + INSERT INTO artist_release_group_pending_update VALUES (release_group_id); +END; +$$ LANGUAGE 'plpgsql'; + +UPDATE release_group_meta SET first_release_date_year = first.year, + first_release_date_month = first.month, + first_release_date_day = first.day + FROM ( + SELECT DISTINCT ON (release_group.id) + release_group.id AS release_group, rd.year, rd.month, rd.day + FROM release_group + LEFT JOIN release ON release.release_group = release_group.id + LEFT JOIN release_first_release_date rd ON (rd.release = release.id) + ORDER BY + release_group.id, + rd.year NULLS LAST, + rd.month NULLS LAST, + rd.day NULLS LAST + ) AS first +WHERE id = first.release_group + AND ( + first_release_date_year IS DISTINCT FROM first.year + OR first_release_date_month IS DISTINCT FROM first.month + OR first_release_date_day IS DISTINCT FROM first.day + ); + +COMMIT; diff --git a/mbslave/sql/updates/schema-change/30.all.sql b/mbslave/sql/updates/schema-change/30.all.sql new file mode 100644 index 0000000..2a2743d --- /dev/null +++ b/mbslave/sql/updates/schema-change/30.all.sql @@ -0,0 +1,401 @@ +-- Generated by CompileSchemaScripts.pl from: +-- 20241017-mbs-9253-13464.sql +-- 20250408-mbs-13322.sql +-- 20250425-mbs-13464.sql +-- 20241125-mbs-13832.sql +-- 20250320-mbs-13768.sql +-- 20250408-mbs-13964-all.sql +-- 20250425-mbs-13966.sql +\set ON_ERROR_STOP 1 +BEGIN; +SET search_path = musicbrainz, public; +SET LOCAL statement_timeout = 0; +-------------------------------------------------------------------------------- +SELECT '20241017-mbs-9253-13464.sql'; + + +DROP TRIGGER IF EXISTS a_upd_release_group_primary_type ON release_group_primary_type; +DROP TRIGGER IF EXISTS a_upd_release_group_secondary_type ON release_group_secondary_type; + +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON release_group_primary_type; +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates ON release_group_secondary_type; + +DROP FUNCTION get_artist_release_group_rows(integer); + +DROP INDEX artist_release_group_nonva_idx_sort; +DROP INDEX artist_release_group_va_idx_sort; + +DROP TABLE artist_release_group_nonva; +DROP TABLE artist_release_group_va; +DROP TABLE artist_release_group; + +CREATE TABLE artist_release_group ( + -- See comment for `artist_release.is_track_artist`. + is_track_artist BOOLEAN NOT NULL, + artist INTEGER NOT NULL, -- references artist.id, CASCADE + unofficial BOOLEAN NOT NULL, + primary_type_child_order SMALLINT, + primary_type SMALLINT, + secondary_type_child_orders SMALLINT[], + secondary_types SMALLINT[], + first_release_date INTEGER, + name VARCHAR COLLATE musicbrainz NOT NULL, + release_group INTEGER NOT NULL -- references release_group.id, CASCADE +) PARTITION BY LIST (is_track_artist); + +CREATE TABLE artist_release_group_nonva + PARTITION OF artist_release_group FOR VALUES IN (FALSE); + +CREATE TABLE artist_release_group_va + PARTITION OF artist_release_group FOR VALUES IN (TRUE); + +CREATE OR REPLACE FUNCTION get_artist_release_group_rows( + release_group_id INTEGER +) RETURNS SETOF artist_release_group AS $$ +BEGIN + -- PostgreSQL 12 generates a vastly more efficient plan when only + -- one release group ID is passed. A condition like + -- `rg.id = any(...)` can be over 200x slower, even with only one + -- release group ID in the array. + RETURN QUERY EXECUTE $SQL$ + SELECT DISTINCT ON (a_rg.artist, rg.id) + a_rg.is_track_artist, + a_rg.artist, + -- Withdrawn releases were once official by definition + bool_and(r.status IS NOT NULL AND r.status != 1 AND r.status != 5), + rgpt.child_order::SMALLINT, + rg.type::SMALLINT, + array_agg( + DISTINCT rgst.child_order ORDER BY rgst.child_order) + FILTER (WHERE rgst.child_order IS NOT NULL + )::SMALLINT[], + array_agg( + DISTINCT st.secondary_type ORDER BY st.secondary_type) + FILTER (WHERE st.secondary_type IS NOT NULL + )::SMALLINT[], + integer_date( + rgm.first_release_date_year, + rgm.first_release_date_month, + rgm.first_release_date_day + ), + rg.name, + rg.id + FROM ( + SELECT FALSE AS is_track_artist, rgacn.artist, rg.id AS release_group + FROM release_group rg + JOIN artist_credit_name rgacn ON rgacn.artist_credit = rg.artist_credit + UNION ALL + SELECT TRUE AS is_track_artist, tacn.artist, r.release_group + FROM release r + JOIN medium m ON m.release = r.id + JOIN track t ON t.medium = m.id + JOIN artist_credit_name tacn ON tacn.artist_credit = t.artist_credit + ) a_rg + JOIN release_group rg ON rg.id = a_rg.release_group + LEFT JOIN release r ON r.release_group = rg.id + JOIN release_group_meta rgm ON rgm.id = rg.id + LEFT JOIN release_group_primary_type rgpt ON rgpt.id = rg.type + LEFT JOIN release_group_secondary_type_join st ON st.release_group = rg.id + LEFT JOIN release_group_secondary_type rgst ON rgst.id = st.secondary_type + $SQL$ || (CASE WHEN release_group_id IS NULL THEN '' ELSE 'WHERE rg.id = $1' END) || + $SQL$ + GROUP BY a_rg.is_track_artist, a_rg.artist, rgm.id, rg.id, rgpt.child_order + ORDER BY a_rg.artist, rg.id, a_rg.is_track_artist + $SQL$ + USING release_group_id; +END; +$$ LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION a_upd_release_group_primary_type_mirror() +RETURNS trigger AS $$ +BEGIN + -- DO NOT modify any replicated tables in this function; it's used + -- by a trigger on mirrors. + IF (NEW.child_order IS DISTINCT FROM OLD.child_order) + THEN + INSERT INTO artist_release_group_pending_update ( + SELECT id FROM release_group + WHERE release_group.type = OLD.id + ); + END IF; + RETURN NULL; +END; +$$ LANGUAGE 'plpgsql'; + +CREATE OR REPLACE FUNCTION a_upd_release_group_secondary_type_mirror() +RETURNS trigger AS $$ +BEGIN + -- DO NOT modify any replicated tables in this function; it's used + -- by a trigger on mirrors. + IF (NEW.child_order IS DISTINCT FROM OLD.child_order) + THEN + INSERT INTO artist_release_group_pending_update ( + SELECT release_group + FROM release_group_secondary_type_join + WHERE secondary_type = OLD.id + ); + END IF; + RETURN NULL; +END; +$$ LANGUAGE 'plpgsql'; + +CREATE INDEX artist_release_group_nonva_idx_sort ON artist_release_group_nonva (artist, unofficial, primary_type_child_order NULLS FIRST, primary_type NULLS FIRST, secondary_type_child_orders NULLS FIRST, secondary_types NULLS FIRST, first_release_date NULLS LAST, name, release_group); +CREATE INDEX artist_release_group_va_idx_sort ON artist_release_group_va (artist, unofficial, primary_type_child_order NULLS FIRST, primary_type NULLS FIRST, secondary_type_child_orders NULLS FIRST, secondary_types NULLS FIRST, first_release_date NULLS LAST, name, release_group); + +CREATE UNIQUE INDEX artist_release_group_nonva_idx_uniq ON artist_release_group_nonva (release_group, artist); +CREATE UNIQUE INDEX artist_release_group_va_idx_uniq ON artist_release_group_va (release_group, artist); + +-------------------------------------------------------------------------------- +SELECT '20250408-mbs-13322.sql'; + + +CREATE OR REPLACE FUNCTION delete_unused_url(ids INTEGER[]) +RETURNS VOID AS $$ +BEGIN + DELETE FROM url_gid_redirect WHERE new_id = any(ids); + DELETE FROM url WHERE id = any(ids); +EXCEPTION + WHEN foreign_key_violation THEN RETURN; +END; +$$ LANGUAGE 'plpgsql'; + +-------------------------------------------------------------------------------- +SELECT '20250425-mbs-13464.sql'; + + +DROP FUNCTION get_artist_release_rows(integer); + +DROP TABLE artist_release_nonva; +DROP TABLE artist_release_va; +DROP TABLE artist_release; + +CREATE TABLE artist_release ( + is_track_artist BOOLEAN NOT NULL, + artist INTEGER NOT NULL, + first_release_date INTEGER, + catalog_numbers TEXT[], + country_code CHAR(2), + barcode BIGINT, + name VARCHAR COLLATE musicbrainz NOT NULL, + release INTEGER NOT NULL +) PARTITION BY LIST (is_track_artist); + +CREATE TABLE artist_release_nonva + PARTITION OF artist_release FOR VALUES IN (FALSE); + +CREATE TABLE artist_release_va + PARTITION OF artist_release FOR VALUES IN (TRUE); + +CREATE OR REPLACE FUNCTION get_artist_release_rows( + release_id INTEGER +) RETURNS SETOF artist_release AS $$ +BEGIN + -- PostgreSQL 12 generates a vastly more efficient plan when only + -- one release ID is passed. A condition like `r.id = any(...)` + -- can be over 200x slower, even with only one release ID in the + -- array. + RETURN QUERY EXECUTE $SQL$ + SELECT DISTINCT ON (ar.artist, r.id) + ar.is_track_artist, + ar.artist, + integer_date(rfrd.year, rfrd.month, rfrd.day) AS first_release_date, + array_agg( + DISTINCT rl.catalog_number ORDER BY rl.catalog_number + ) FILTER (WHERE rl.catalog_number IS NOT NULL)::TEXT[] AS catalog_numbers, + min(iso.code ORDER BY iso.code)::CHAR(2) AS country_code, + left(regexp_replace( + (CASE r.barcode WHEN '' THEN '0' ELSE r.barcode END), + '[^0-9]+', '', 'g' + ), 18)::BIGINT AS barcode, + r.name, + r.id + FROM ( + SELECT FALSE AS is_track_artist, racn.artist, r.id AS release + FROM release r + JOIN artist_credit_name racn ON racn.artist_credit = r.artist_credit + UNION ALL + SELECT TRUE AS is_track_artist, tacn.artist, m.release + FROM medium m + JOIN track t ON t.medium = m.id + JOIN artist_credit_name tacn ON tacn.artist_credit = t.artist_credit + ) ar + JOIN release r ON r.id = ar.release + LEFT JOIN release_first_release_date rfrd ON rfrd.release = r.id + LEFT JOIN release_label rl ON rl.release = r.id + LEFT JOIN release_country rc ON rc.release = r.id + LEFT JOIN iso_3166_1 iso ON iso.area = rc.country + $SQL$ || (CASE WHEN release_id IS NULL THEN '' ELSE 'WHERE r.id = $1' END) || + $SQL$ + GROUP BY ar.is_track_artist, ar.artist, rfrd.release, r.id + ORDER BY ar.artist, r.id, ar.is_track_artist + $SQL$ + USING release_id; +END; +$$ LANGUAGE plpgsql; + +CREATE INDEX artist_release_nonva_idx_sort ON artist_release_nonva (artist, first_release_date NULLS LAST, catalog_numbers NULLS LAST, country_code NULLS LAST, barcode NULLS LAST, name, release); +CREATE INDEX artist_release_va_idx_sort ON artist_release_va (artist, first_release_date NULLS LAST, catalog_numbers NULLS LAST, country_code NULLS LAST, barcode NULLS LAST, name, release); + +CREATE UNIQUE INDEX artist_release_nonva_idx_uniq ON artist_release_nonva (release, artist); +CREATE UNIQUE INDEX artist_release_va_idx_uniq ON artist_release_va (release, artist); + +-------------------------------------------------------------------------------- +SELECT '20241125-mbs-13832.sql'; + + +-- MBS-14014 +DROP VIEW IF EXISTS cover_art_archive.index_listing; + +-- CAA view +CREATE VIEW cover_art_archive.index_listing AS +SELECT cover_art.*, + (edit.close_time IS NOT NULL) AS approved, + coalesce(cover_art.id = (SELECT id FROM cover_art_archive.cover_art_type + JOIN cover_art_archive.cover_art ca_front USING (id) + WHERE ca_front.release = cover_art.release + AND type_id = 1 + ORDER BY ca_front.ordering + LIMIT 1), FALSE) AS is_front, + coalesce(cover_art.id = (SELECT id FROM cover_art_archive.cover_art_type + JOIN cover_art_archive.cover_art ca_front USING (id) + WHERE ca_front.release = cover_art.release + AND type_id = 2 + ORDER BY ca_front.ordering + LIMIT 1), FALSE) AS is_back, + array(SELECT art_type.name + FROM cover_art_archive.cover_art_type + JOIN cover_art_archive.art_type ON cover_art_type.type_id = art_type.id + WHERE cover_art_type.id = cover_art.id) AS types +FROM cover_art_archive.cover_art +LEFT JOIN musicbrainz.edit ON edit.id = cover_art.edit; + +-- EAA view +CREATE OR REPLACE VIEW event_art_archive.index_listing AS +SELECT event_art.*, + (edit.close_time IS NOT NULL) AS approved, + coalesce(event_art.id = (SELECT id FROM event_art_archive.event_art_type + JOIN event_art_archive.event_art ea_front USING (id) + WHERE ea_front.event = event_art.event + AND type_id = 1 + ORDER BY ea_front.ordering + LIMIT 1), FALSE) AS is_front, + array(SELECT art_type.name + FROM event_art_archive.event_art_type + JOIN event_art_archive.art_type ON event_art_type.type_id = art_type.id + WHERE event_art_type.id = event_art.id) AS types +FROM event_art_archive.event_art +LEFT JOIN musicbrainz.edit ON edit.id = event_art.edit; + +-------------------------------------------------------------------------------- +SELECT '20250320-mbs-13768.sql'; + + +-- Medium GID + +-- Creating column +ALTER TABLE medium ADD COLUMN gid uuid; + +-- Generating GIDs +UPDATE medium SET gid = + generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'medium' || id); + +-- Adding NOT NULL constraint +ALTER TABLE medium ALTER COLUMN gid SET NOT NULL; + +-- Creating index +CREATE UNIQUE INDEX medium_idx_gid ON medium (gid); + +-- Medium GID redirect +CREATE TABLE medium_gid_redirect ( -- replicate (verbose) + gid UUID NOT NULL, -- PK + new_id INTEGER NOT NULL, -- references medium.id + created TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + +ALTER TABLE medium_gid_redirect ADD CONSTRAINT medium_gid_redirect_pkey PRIMARY KEY (gid); + +CREATE INDEX medium_gid_redirect_idx_new_id ON medium_gid_redirect (new_id); + +-------------------------------------------------------------------------------- +SELECT '20250408-mbs-13964-all.sql'; + + +CREATE OR REPLACE FUNCTION set_mediums_recordings_first_release_dates(medium_ids INTEGER[]) +RETURNS VOID AS $$ +BEGIN + PERFORM set_recordings_first_release_dates(( + SELECT array_agg(recording) + FROM track + WHERE track.medium = any(medium_ids) + )); + RETURN; +END; +$$ LANGUAGE 'plpgsql' STRICT; + +CREATE OR REPLACE FUNCTION a_upd_medium_mirror() +RETURNS trigger AS $$ +BEGIN + -- DO NOT modify any replicated tables in this function; it's used + -- by a trigger on mirrors. + IF NEW.release IS DISTINCT FROM OLD.release THEN + PERFORM set_mediums_recordings_first_release_dates(ARRAY[OLD.id]); + END IF; + RETURN NULL; +END; +$$ LANGUAGE 'plpgsql'; + +CREATE TRIGGER a_upd_medium AFTER UPDATE ON medium + FOR EACH ROW EXECUTE PROCEDURE a_upd_medium_mirror(); + +TRUNCATE recording_first_release_date; + +-------------------------------------------------------------------------------- +SELECT '20250425-mbs-13966.sql'; + + +CREATE OR REPLACE FUNCTION set_release_group_first_release_date(release_group_id INTEGER) +RETURNS VOID AS $$ +BEGIN + UPDATE release_group_meta SET first_release_date_year = first.year, + first_release_date_month = first.month, + first_release_date_day = first.day + FROM ( + SELECT rd.year, rd.month, rd.day + FROM release_group + LEFT JOIN release ON release.release_group = release_group.id + LEFT JOIN release_first_release_date rd ON (rd.release = release.id) + WHERE release_group.id = release_group_id + ORDER BY + rd.year NULLS LAST, + rd.month NULLS LAST, + rd.day NULLS LAST + LIMIT 1 + ) AS first + WHERE id = release_group_id; + INSERT INTO artist_release_group_pending_update VALUES (release_group_id); +END; +$$ LANGUAGE 'plpgsql'; + +UPDATE release_group_meta SET first_release_date_year = first.year, + first_release_date_month = first.month, + first_release_date_day = first.day + FROM ( + SELECT DISTINCT ON (release_group.id) + release_group.id AS release_group, rd.year, rd.month, rd.day + FROM release_group + LEFT JOIN release ON release.release_group = release_group.id + LEFT JOIN release_first_release_date rd ON (rd.release = release.id) + ORDER BY + release_group.id, + rd.year NULLS LAST, + rd.month NULLS LAST, + rd.day NULLS LAST + ) AS first +WHERE id = first.release_group + AND ( + first_release_date_year IS DISTINCT FROM first.year + OR first_release_date_month IS DISTINCT FROM first.month + OR first_release_date_day IS DISTINCT FROM first.day + ); + +COMMIT; diff --git a/mbslave/sql/updates/schema-change/30.master_and_standalone.sql b/mbslave/sql/updates/schema-change/30.master_and_standalone.sql new file mode 100644 index 0000000..d92cedb --- /dev/null +++ b/mbslave/sql/updates/schema-change/30.master_and_standalone.sql @@ -0,0 +1,74 @@ +-- Generated by CompileSchemaScripts.pl from: +-- 20241017-mbs-9253-master_and_standalone.sql +-- 20250425-mbs-13464-master_and_standalone.sql +-- 20250320-mbs-13768-fks.sql +\set ON_ERROR_STOP 1 +BEGIN; +SET search_path = musicbrainz, public; +SET LOCAL statement_timeout = 0; +-------------------------------------------------------------------------------- +SELECT '20241017-mbs-9253-master_and_standalone.sql'; + +SET search_path = musicbrainz; + + +ALTER TABLE artist_release_group + ADD CONSTRAINT artist_release_group_fk_artist + FOREIGN KEY (artist) + REFERENCES artist(id) + ON DELETE CASCADE; + +ALTER TABLE artist_release_group + ADD CONSTRAINT artist_release_group_fk_release_group + FOREIGN KEY (release_group) + REFERENCES release_group(id) + ON DELETE CASCADE; + +CREATE TRIGGER a_upd_release_group_primary_type AFTER UPDATE ON release_group_primary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_primary_type_mirror(); + +CREATE TRIGGER a_upd_release_group_secondary_type AFTER UPDATE ON release_group_secondary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_secondary_type_mirror(); + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates + AFTER UPDATE ON release_group_primary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates + AFTER UPDATE ON release_group_secondary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +-------------------------------------------------------------------------------- +SELECT '20250425-mbs-13464-master_and_standalone.sql'; + +SET search_path = musicbrainz; + + +ALTER TABLE artist_release + ADD CONSTRAINT artist_release_fk_artist + FOREIGN KEY (artist) + REFERENCES artist(id) + ON DELETE CASCADE; + +ALTER TABLE artist_release + ADD CONSTRAINT artist_release_fk_release + FOREIGN KEY (release) + REFERENCES release(id) + ON DELETE CASCADE; + +-------------------------------------------------------------------------------- +SELECT '20250320-mbs-13768-fks.sql'; + +SET search_path = musicbrainz; + + +ALTER TABLE medium_gid_redirect + ADD CONSTRAINT medium_gid_redirect_fk_new_id + FOREIGN KEY (new_id) + REFERENCES medium(id); + +COMMIT; diff --git a/mbslave/sql/updates/schema-change/30.mirror_only.sql b/mbslave/sql/updates/schema-change/30.mirror_only.sql new file mode 100644 index 0000000..3cf3038 --- /dev/null +++ b/mbslave/sql/updates/schema-change/30.mirror_only.sql @@ -0,0 +1,37 @@ +-- Generated by CompileSchemaScripts.pl from: +-- 20241017-mbs-9253-mirror_only.sql +\set ON_ERROR_STOP 1 +BEGIN; +SET search_path = musicbrainz, public; +SET LOCAL statement_timeout = 0; +-------------------------------------------------------------------------------- +SELECT '20241017-mbs-9253-mirror_only.sql'; + + +DROP TRIGGER IF EXISTS a_upd_release_group_primary_type_mirror ON release_group_primary_type; + +CREATE TRIGGER a_upd_release_group_primary_type_mirror AFTER UPDATE ON release_group_primary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_primary_type_mirror(); + +DROP TRIGGER IF EXISTS a_upd_release_group_secondary_type_mirror ON release_group_secondary_type; + +CREATE TRIGGER a_upd_release_group_secondary_type_mirror AFTER UPDATE ON release_group_secondary_type + FOR EACH ROW EXECUTE PROCEDURE a_upd_release_group_secondary_type_mirror(); + +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON release_group_primary_type; + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates_mirror + AFTER UPDATE ON release_group_primary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +DROP TRIGGER IF EXISTS apply_artist_release_group_pending_updates_mirror ON release_group_secondary_type; + +CREATE CONSTRAINT TRIGGER apply_artist_release_group_pending_updates_mirror + AFTER UPDATE ON release_group_secondary_type DEFERRABLE INITIALLY DEFERRED + FOR EACH ROW + WHEN (OLD.child_order IS DISTINCT FROM NEW.child_order) + EXECUTE PROCEDURE apply_artist_release_group_pending_updates(); + +COMMIT; From 4237f63966c19ea1c9effbd2ed0e4ad797423e50 Mon Sep 17 00:00:00 2001 From: Harald Friessnegger Date: Mon, 26 May 2025 10:35:47 +0200 Subject: [PATCH 3/4] update upgrade scripts musicbrainz has fixed upgrade issues see https://github.com/metabrainz/musicbrainz-server/commit/c7b8c2925f210a754875a3b7b35315ed2d715c9a --- mbslave/sql/updates/20250425-mbs-13966.sql | 21 +++++++++++++++++++- mbslave/sql/updates/schema-change/30.all.sql | 21 +++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/mbslave/sql/updates/20250425-mbs-13966.sql b/mbslave/sql/updates/20250425-mbs-13966.sql index 3792cdb..3a56b05 100644 --- a/mbslave/sql/updates/20250425-mbs-13966.sql +++ b/mbslave/sql/updates/20250425-mbs-13966.sql @@ -25,6 +25,16 @@ BEGIN END; $$ LANGUAGE 'plpgsql'; +CREATE TEMPORARY TABLE tmp_release_first_release_date_2025_q2 ( + release INTEGER NOT NULL PRIMARY KEY, + year SMALLINT, + month SMALLINT, + day SMALLINT +) ON COMMIT DROP; + +INSERT INTO tmp_release_first_release_date_2025_q2 + SELECT * FROM get_release_first_release_date_rows('TRUE'); + UPDATE release_group_meta SET first_release_date_year = first.year, first_release_date_month = first.month, first_release_date_day = first.day @@ -33,7 +43,7 @@ UPDATE release_group_meta SET first_release_date_year = first.year, release_group.id AS release_group, rd.year, rd.month, rd.day FROM release_group LEFT JOIN release ON release.release_group = release_group.id - LEFT JOIN release_first_release_date rd ON (rd.release = release.id) + LEFT JOIN tmp_release_first_release_date_2025_q2 rd ON (rd.release = release.id) ORDER BY release_group.id, rd.year NULLS LAST, @@ -47,4 +57,13 @@ WHERE id = first.release_group OR first_release_date_day IS DISTINCT FROM first.day ); +-- Mirrors have a `a_upd_release_group_meta_mirror` trigger which inserts +-- updated `release_group_meta` IDs into `artist_release_group_pending_update`, +-- which in turn causes the associated entries in `artist_release_group` +-- to be updated. That should be a no-op here, because the schema 30 upgrade +-- already truncates `artist_release_group` (via dropping and recreating it) +-- before this runs; but clear it anyway to avoid a pointless calculation in +-- the `apply_artist_release_group_pending_updates` function. +TRUNCATE artist_release_group_pending_update; + COMMIT; diff --git a/mbslave/sql/updates/schema-change/30.all.sql b/mbslave/sql/updates/schema-change/30.all.sql index 2a2743d..c9d8553 100644 --- a/mbslave/sql/updates/schema-change/30.all.sql +++ b/mbslave/sql/updates/schema-change/30.all.sql @@ -376,6 +376,16 @@ BEGIN END; $$ LANGUAGE 'plpgsql'; +CREATE TEMPORARY TABLE tmp_release_first_release_date_2025_q2 ( + release INTEGER NOT NULL PRIMARY KEY, + year SMALLINT, + month SMALLINT, + day SMALLINT +) ON COMMIT DROP; + +INSERT INTO tmp_release_first_release_date_2025_q2 + SELECT * FROM get_release_first_release_date_rows('TRUE'); + UPDATE release_group_meta SET first_release_date_year = first.year, first_release_date_month = first.month, first_release_date_day = first.day @@ -384,7 +394,7 @@ UPDATE release_group_meta SET first_release_date_year = first.year, release_group.id AS release_group, rd.year, rd.month, rd.day FROM release_group LEFT JOIN release ON release.release_group = release_group.id - LEFT JOIN release_first_release_date rd ON (rd.release = release.id) + LEFT JOIN tmp_release_first_release_date_2025_q2 rd ON (rd.release = release.id) ORDER BY release_group.id, rd.year NULLS LAST, @@ -398,4 +408,13 @@ WHERE id = first.release_group OR first_release_date_day IS DISTINCT FROM first.day ); +-- Mirrors have a `a_upd_release_group_meta_mirror` trigger which inserts +-- updated `release_group_meta` IDs into `artist_release_group_pending_update`, +-- which in turn causes the associated entries in `artist_release_group` +-- to be updated. That should be a no-op here, because the schema 30 upgrade +-- already truncates `artist_release_group` (via dropping and recreating it) +-- before this runs; but clear it anyway to avoid a pointless calculation in +-- the `apply_artist_release_group_pending_updates` function. +TRUNCATE artist_release_group_pending_update; + COMMIT; From 4c601fcc596d287133372bf3de04057d791fb72c Mon Sep 17 00:00:00 2001 From: Harald Friessnegger Date: Tue, 27 May 2025 21:54:44 +0200 Subject: [PATCH 4/4] mention search_path problem and possible fix --- README.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 211fd8a..25282b8 100644 --- a/README.rst +++ b/README.rst @@ -36,7 +36,7 @@ There are two ways to configure the application. export MBSLAVE_CONFIG=/usr/local/etc/mbslave.conf -2. Alternativelly, you can use using environment variables:: +2. Alternatively, you can use environment variables:: export MBSLAVE_DB_HOST=127.0.0.1 export MBSLAVE_DB_PORT=5432 @@ -46,6 +46,14 @@ There are two ways to configure the application. export MBSLAVE_DB_ADMIN_USER=postgres export MBSLAVE_DB_ADMIN_PASSWORD=XXX +Be aware, that configuring a different value for `db.user` or `schemas.musicbrainz` might require to configure a +custom `search_path` for the user (or database): By default, postgres sets the search_path to `"$user", public`. +If both is `musicbrainz` everything works, if they differ, you might run into errors when running `mbslave sync` as +triggers can't lookup functions properly. One way to solve this is to set the search path for your custom user to the +schema configured for musicbrainz:: + + ALTER USER myuser SET search_path TO musicbrainz, public; + Database Setup ==============