@@ -9,10 +9,14 @@ DECLARE
99 target_bracket tournament_brackets%ROWTYPE;
1010 slot_position int ;
1111BEGIN
12+ -- Lock the target row so concurrent callers (e.g. two feeder matches
13+ -- finishing simultaneously) serialize on the same bracket. Combined with
14+ -- the IS NULL guards on the UPDATEs below, this prevents either caller
15+ -- from overwriting a team the other just placed.
1216 SELECT * INTO target_bracket
1317 FROM tournament_brackets
1418 WHERE id = _target_bracket_id
15- LIMIT 1 ;
19+ FOR UPDATE ;
1620
1721 IF target_bracket IS NULL OR _team_id IS NULL THEN
1822 RETURN;
@@ -44,36 +48,45 @@ BEGIN
4448 WHERE ranked .id = _source_bracket_id;
4549 END IF;
4650
51+ -- Every UPDATE carries an IS NULL guard as defense-in-depth alongside the
52+ -- row lock, so a slot can never be overwritten even if a caller bypasses
53+ -- the lock (e.g. direct mutation outside this function).
4754 IF slot_position = 1 THEN
4855 IF target_bracket .tournament_team_id_1 IS NULL THEN
4956 UPDATE tournament_brackets
5057 SET tournament_team_id_1 = _team_id
51- WHERE id = _target_bracket_id;
58+ WHERE id = _target_bracket_id
59+ AND tournament_team_id_1 IS NULL ;
5260 ELSIF target_bracket .tournament_team_id_2 IS NULL THEN
5361 UPDATE tournament_brackets
5462 SET tournament_team_id_2 = _team_id
55- WHERE id = _target_bracket_id;
63+ WHERE id = _target_bracket_id
64+ AND tournament_team_id_2 IS NULL ;
5665 END IF;
5766 ELSIF slot_position = 2 THEN
5867 IF target_bracket .tournament_team_id_2 IS NULL THEN
5968 UPDATE tournament_brackets
6069 SET tournament_team_id_2 = _team_id
61- WHERE id = _target_bracket_id;
70+ WHERE id = _target_bracket_id
71+ AND tournament_team_id_2 IS NULL ;
6272 ELSIF target_bracket .tournament_team_id_1 IS NULL THEN
6373 UPDATE tournament_brackets
6474 SET tournament_team_id_1 = _team_id
65- WHERE id = _target_bracket_id;
75+ WHERE id = _target_bracket_id
76+ AND tournament_team_id_1 IS NULL ;
6677 END IF;
6778 ELSE
6879 -- Fallback: first empty slot (for callers without source bracket)
6980 IF target_bracket .tournament_team_id_1 IS NULL THEN
7081 UPDATE tournament_brackets
7182 SET tournament_team_id_1 = _team_id
72- WHERE id = _target_bracket_id;
83+ WHERE id = _target_bracket_id
84+ AND tournament_team_id_1 IS NULL ;
7385 ELSIF target_bracket .tournament_team_id_2 IS NULL THEN
7486 UPDATE tournament_brackets
7587 SET tournament_team_id_2 = _team_id
76- WHERE id = _target_bracket_id;
88+ WHERE id = _target_bracket_id
89+ AND tournament_team_id_2 IS NULL ;
7790 END IF;
7891 END IF;
7992END;
0 commit comments