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..25282b8 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 @@ -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 ============== @@ -82,6 +90,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" 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..3a56b05 --- /dev/null +++ b/mbslave/sql/updates/20250425-mbs-13966.sql @@ -0,0 +1,69 @@ +\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'; + +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 + 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 tmp_release_first_release_date_2025_q2 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 + ); + +-- 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 new file mode 100644 index 0000000..c9d8553 --- /dev/null +++ b/mbslave/sql/updates/schema-change/30.all.sql @@ -0,0 +1,420 @@ +-- 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'; + +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 + 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 tmp_release_first_release_date_2025_q2 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 + ); + +-- 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.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;