From 9acd45e9cc6bc6b82de28d292dd527b661de1e46 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Sat, 13 Apr 2024 15:38:53 -0400 Subject: [PATCH] importer: rgl: Support combining teams Add support for combining teams that have been linked after already having been imported. This occasionally happens by request. Signed-off-by: Sean Anderson --- test/create.py | 23 +++++++++++-- trends/importer/league.py | 45 +++++++++++++++++++++---- trends/migrations/deferrable_teamid.sql | 8 +++++ trends/schema.sql | 11 +++--- 4 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 trends/migrations/deferrable_teamid.sql diff --git a/test/create.py b/test/create.py index 3ceacda..85428d7 100755 --- a/test/create.py +++ b/test/create.py @@ -13,6 +13,22 @@ from trends.importer.fetch import DemoFileFetcher, ETF2LFileFetcher, FileFetcher, RGLFileFetcher from trends.sql import db_connect, db_init, db_schema +# Pretend these two teams aren't linked so we can test combining them +class RGLFirstFetcher(RGLFileFetcher): + def get_team(self, teamid): + ret = super().get_team(teamid) + if teamid == 5574: + ret['linkedTeams'] = [] + ret['fetched'] = 1 + if teamid == 4882: + ret['linkedTeams'] = [] + ret['fetched'] = 1 + return ret + +class RGLSecondFetcher(RGLFileFetcher): + def get_matchids(self): + yield 4664 + def create_test_db(url): # We use separate connections for importing because we use temporary tables which will alias # other queries. @@ -82,9 +98,10 @@ def create_test_db(url): trends.importer.etf2l.import_etf2l(c, fetcher) with db_connect(url) as c: - fetcher = RGLFileFetcher(dir=f"{os.path.dirname(__file__)}/rgl") - trends.importer.rgl.import_rgl(c, fetcher) - + dir = f"{os.path.dirname(__file__)}/rgl" + trends.importer.rgl.import_rgl(c, RGLFirstFetcher(dir=dir)) + trends.importer.rgl.import_rgl(c, RGLSecondFetcher(dir=dir), + filter=trends.importer.rgl.no_filter_matchids) with db_connect(url) as c: cur = c.cursor() cur.execute("ANALYZE;") diff --git a/trends/importer/league.py b/trends/importer/league.py index 5e87c77..289b8ac 100644 --- a/trends/importer/league.py +++ b/trends/importer/league.py @@ -37,6 +37,38 @@ def import_compdiv(c, cd): (SELECT div_nameid FROM div_name WHERE division = %(division)s), %(tier)s ) ON CONFLICT DO NOTHING;""", cd) +def combine_teams(c, league, teamids): + """Combine teams + Combine the teams specified into one team. This may occasionally be necessary when RGL teams are + retroactively linked. + """ + + new_teamid = min(teamids) + teamids = tuple(teamid for teamid in teamids if teamid != new_teamid) + def set_constraints(behavior): + c.execute( + f"""SET CONSTRAINTS + team_player_league_teamid_fkey, + team_player_league_teamid_compid_fkey, + match_league_compid_teamid1_fkey, + match_league_compid_teamid2_fkey + {behavior};"""); + + set_constraints("DEFERRED") + for table, col in ( + ('team_comp_backing', 'teamid'), + ('team_player', 'teamid'), + ('match', 'teamid1'), + ('match', 'teamid2'), + ): + c.execute( + f"""UPDATE {table} + SET {col} = %s + WHERE league = %s AND {col} IN %s;""", (new_teamid, league, teamids)) + set_constraints("IMMEDIATE") + + return new_teamid + def import_team(c, t): """Import a team The competition and division should already be imported. t should be a dict with the following @@ -69,13 +101,14 @@ def import_team(c, t): if teamids := t.get('rgl_teamids'): c.execute("SELECT teamid FROM team_comp WHERE rgl_teamid IN %s GROUP BY teamid", (teamids,)) - if c.rowcount not in (0, 1): - logging.warning("Too many matching teams for linked RGL teamids %s", teamids) - - if row := c.fetchone(): - t['teamid'] = row[0] + if c.rowcount > 1: + logging.info("Combining RGL teamids %s", teamids) + t['teamid'] = combine_teams(c, t['league'], tuple(row[0] for row in c.fetchall())) else: - teamid_col = min(teamids) + if row := c.fetchone(): + t['teamid'] = row[0] + else: + teamid_col = min(teamids) c.execute("INSERT INTO team_name (team) VALUES (%(name)s) ON CONFLICT DO NOTHING", t) c.execute( diff --git a/trends/migrations/deferrable_teamid.sql b/trends/migrations/deferrable_teamid.sql new file mode 100644 index 0000000..9f4af7c --- /dev/null +++ b/trends/migrations/deferrable_teamid.sql @@ -0,0 +1,8 @@ +BEGIN; +ALTER TABLE team_player + ALTER CONSTRAINT team_player_league_teamid_fkey DEFERRABLE, + ALTER CONSTRAINT team_player_league_teamid_compid_fkey DEFERRABLE; +ALTER TABLE match + ALTER CONSTRAINT match_league_compid_teamid1_fkey DEFERRABLE, + ALTER CONSTRAINT match_league_compid_teamid2_fkey DEFERRABLE; +COMMIT; diff --git a/trends/schema.sql b/trends/schema.sql index 072836c..c6f475a 100644 --- a/trends/schema.sql +++ b/trends/schema.sql @@ -238,8 +238,9 @@ CREATE TABLE IF NOT EXISTS team_player ( rostered WITH &&, playerid WITH = ) WHERE (compid ISNULL), - FOREIGN KEY (league, teamid) REFERENCES league_team (league, teamid), - FOREIGN KEY (league, teamid, compid) REFERENCES team_comp_backing (league, teamid, compid), + FOREIGN KEY (league, teamid) REFERENCES league_team (league, teamid) DEFERRABLE, + FOREIGN KEY (league, teamid, compid) + REFERENCES team_comp_backing (league, teamid, compid) DEFERRABLE, CHECK (league_team_per_comp(league) = (compid NOTNULL)) ); @@ -295,8 +296,10 @@ CREATE TABLE IF NOT EXISTS match ( FOREIGN KEY (league, round_compid, round_seq) REFERENCES comp_round (league, compid, round_seq), FOREIGN KEY (league, divid, round_seq) REFERENCES div_round (league, divid, round_seq), - FOREIGN KEY (league, compid, teamid1) REFERENCES team_comp_backing (league, compid, teamid), - FOREIGN KEY (league, compid, teamid2) REFERENCES team_comp_backing (league, compid, teamid), + FOREIGN KEY (league, compid, teamid1) + REFERENCES team_comp_backing (league, compid, teamid) DEFERRABLE, + FOREIGN KEY (league, compid, teamid2) + REFERENCES team_comp_backing (league, compid, teamid) DEFERRABLE, CHECK (teamid1 < teamid2), CHECK (league_div_optional(league) OR (divid NOTNULL)), CHECK (league_time_optional(league) OR forfeit OR (scheduled NOTNULL)),