Skip to content

Commit 29104e6

Browse files
authored
Merge pull request #825 from Path-of-Modifiers/revert-822-revert-819-812-make-modifier-id-unique-per-modfier
Revert "Revert "812 make modifier id unique per modfier""
2 parents 76264a2 + d503e63 commit 29104e6

89 files changed

Lines changed: 928 additions & 576 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA
3737

3838
# League
3939
CURRENT_SOFTCORE_LEAGUE="Mirage"
40+
ALL_SOFTCORE_LEAGUES="Mirage|Keepers|Mercenaries|Phrecia"
4041

4142
LEAGUE_LAUNCH_TIME=2026-03-06T19:00:00Z # ISO 8601 format. Round backwards to whole hour number
4243

src/backend_api/app/alembic/replaceable_objects/main.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ def __init__(self, name, sqltext):
1212

1313

1414
class ReplaceableTrigger(ReplaceableObject):
15-
def __init__(self, name, table, function, trigger):
15+
def __init__(self, name: str, table: str, function: str, trigger: str):
1616
self.name = name
1717
self.table = table
18-
self.function = function
19-
self.trigger = trigger
18+
self.function = function.format(name=name)
19+
self.trigger = trigger.format(name=name, table=table)
2020

2121

2222
ObjectType = TypeVar("ObjectType", bound=ReplaceableObject)
@@ -89,22 +89,24 @@ def reverse(self):
8989
@Operations.implementation_for(CreateViewOp)
9090
def create_view(operations: Operations, operation: CreateViewOp):
9191
operations.execute(
92-
"CREATE VIEW %s AS %s" % (operation.target.name, operation.target.sqltext)
92+
"CREATE VIEW {} AS {}".format(operation.target.name, operation.target.sqltext)
9393
)
9494

9595

9696
@Operations.implementation_for(DropViewOp)
9797
def drop_view(operations: Operations, operation: DropViewOp):
98-
operations.execute("DROP VIEW %s" % operation.target.name)
98+
operations.execute("DROP VIEW {}".format(operation.target.name))
9999

100100

101101
@Operations.implementation_for(CreateTriggerOp)
102102
def create_trigger(operations: Operations, operation: CreateTriggerOp):
103103
operations.execute(
104-
"CREATE FUNCTION %s() %s" % (operation.target.name, operation.target.function)
104+
"CREATE FUNCTION {}() {}".format(
105+
operation.target.name, operation.target.function
106+
)
105107
)
106108
operations.execute(
107-
"CREATE TRIGGER %s %s" % (operation.target.name, operation.target.trigger)
109+
"CREATE TRIGGER {} {}".format(operation.target.name, operation.target.trigger)
108110
)
109111

110112

@@ -113,4 +115,4 @@ def drop_trigger(operations: Operations, operation: DropTriggerOp):
113115
operations.execute(
114116
"DROP TRIGGER {} ON {};".format(operation.target.name, operation.target.table)
115117
)
116-
operations.execute("DROP FUNCTION %s();" % operation.target.name)
118+
operations.execute("DROP FUNCTION {}();".format(operation.target.name))
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
"""Removing modifier auto increment
2+
3+
Revision ID: 17daa1c96438
4+
Revises: cc39d4eb113b
5+
Create Date: 2026-05-09 16:05:14.813497
6+
7+
"""
8+
9+
from typing import Sequence, Union
10+
11+
from alembic import op
12+
import sqlalchemy as sa
13+
14+
from app.alembic.replaceable_objects.main import ReplaceableTrigger
15+
16+
# revision identifiers, used by Alembic.
17+
revision: str = "17daa1c96438"
18+
down_revision: Union[str, None] = "cc39d4eb113b"
19+
branch_labels: Union[str, Sequence[str], None] = None
20+
depends_on: Union[str, Sequence[str], None] = None
21+
22+
modifier_id_trigger = ReplaceableTrigger(
23+
"increment_modifier_id",
24+
"modifier",
25+
"""
26+
RETURNS trigger AS ${name}$
27+
DECLARE
28+
exists boolean;
29+
BEGIN
30+
exists := EXISTS(SELECT 1 FROM modifier WHERE "effect" = NEW.effect);
31+
IF NOT exists THEN
32+
NEW."modifierId" := nextval('modifier_id_seq');
33+
34+
ELSIF exists THEN
35+
NEW."modifierId" := (SELECT "modifierId" FROM modifier WHERE "effect" = NEW.effect LIMIT 1);
36+
END IF;
37+
38+
RETURN NEW;
39+
END;
40+
${name}$ LANGUAGE plpgsql;
41+
""",
42+
"""
43+
BEFORE INSERT ON {table}
44+
FOR EACH ROW
45+
EXECUTE FUNCTION {name}();
46+
""",
47+
)
48+
49+
50+
def upgrade() -> None:
51+
# ### commands auto generated by Alembic - please adjust! ###
52+
53+
# droping old item_modifier key
54+
op.drop_constraint(
55+
op.f("item_modifier_modifierId_fkey"), "item_modifier", type_="foreignkey"
56+
)
57+
op.drop_constraint(
58+
op.f("item_modifier_modifierId_fkey1"), "item_modifier", type_="foreignkey"
59+
)
60+
61+
# Dropping old modifier keys
62+
op.f("""ALTER TABLE modifier ALTER COLUMN "modifierId" DROP IDENTITY;""")
63+
op.drop_constraint(op.f("modifier_pkey"), "modifier", type_="primary")
64+
op.drop_constraint(
65+
op.f("modifier_modifierId_position_key"), "modifier", type_="unique"
66+
)
67+
68+
# creating new keys
69+
op.create_primary_key("modifier_pkey", "modifier", ["modifierId", "position"])
70+
op.add_column(
71+
"item_modifier", sa.Column("position", sa.SmallInteger(), nullable=False)
72+
)
73+
op.create_foreign_key(
74+
"fk_item_modifier_modfierId_position",
75+
"item_modifier",
76+
"modifier",
77+
["modifierId", "position"],
78+
["modifierId", "position"],
79+
ondelete="CASCADE",
80+
onupdate="CASCADE",
81+
)
82+
83+
op.execute("""
84+
UPDATE modifier AS m
85+
SET "modifierId" = "modifierId" + 10000;
86+
""")
87+
88+
op.execute("""
89+
WITH subquery as (SELECT
90+
DENSE_RANK() OVER (
91+
ORDER BY m.effect
92+
) AS newModifierId,
93+
m."position",
94+
m."modifierId" AS modifierId
95+
FROM modifier AS m
96+
ORDER BY newModifierId, m.position)
97+
98+
UPDATE modifier AS m
99+
SET "modifierId" = sq.newModifierId
100+
FROM subquery AS sq
101+
WHERE "modifierId" = sq.modifierId;
102+
""")
103+
104+
op.execute("CREATE SEQUENCE modifier_id_seq;")
105+
op.execute(
106+
"""SELECT setval('modifier_id_seq', (SELECT MAX("modifierId") FROM modifier));"""
107+
)
108+
109+
op.create_trigger(modifier_id_trigger)
110+
# ### end Alembic commands ###
111+
112+
113+
def downgrade() -> None:
114+
# ### commands auto generated by Alembic - please adjust! ###
115+
op.drop_trigger(modifier_id_trigger)
116+
117+
# dropping new modifier keys
118+
op.drop_constraint(
119+
op.f("fk_item_modifier_modfierId_position"), "item_modifier", type_="foreignkey"
120+
)
121+
op.drop_column("item_modifier", "position")
122+
op.drop_constraint(op.f("modifier_pkey"), "modifier", type_="primary")
123+
124+
op.execute("""
125+
WITH subquery as (SELECT
126+
ROW_NUMBER() OVER(ORDER BY "modifierId", position ASC) AS newModifierId,
127+
m."position",
128+
m."modifierId" AS modifierId
129+
FROM modifier AS m
130+
ORDER BY newModifierId, m.position)
131+
132+
UPDATE modifier AS m
133+
SET "modifierId" = sq.newModifierId
134+
FROM subquery AS sq
135+
WHERE "modifierId" = sq.modifierId
136+
AND m.position = sq.position;
137+
""")
138+
139+
op.execute("""
140+
DROP SEQUENCE modifier_id_seq;
141+
""")
142+
143+
# adding old keys
144+
op.create_primary_key("modifier_pkey", "modifier", ["modifierId"])
145+
op.create_unique_constraint(
146+
op.f("modifier_modifierId_position_key"),
147+
"modifier",
148+
["modifierId", "position"],
149+
postgresql_nulls_not_distinct=False,
150+
)
151+
152+
op.create_foreign_key(
153+
"item_modifier_modifierId_fkey",
154+
"item_modifier",
155+
"modifier",
156+
["modifierId"],
157+
["modifierId"],
158+
)
159+
op.create_foreign_key(
160+
"item_modifier_modifierId_fkey1",
161+
"item_modifier",
162+
"modifier",
163+
["modifierId"],
164+
["modifierId"],
165+
)
166+
167+
op.alter_column(
168+
"modifier",
169+
"modifierId",
170+
existing_type=sa.SMALLINT(),
171+
server_default=sa.Identity(
172+
always=False,
173+
start=1,
174+
increment=1,
175+
minvalue=1,
176+
maxvalue=32767,
177+
cycle=True,
178+
cache=1,
179+
),
180+
existing_nullable=False,
181+
)
182+
op.execute(
183+
"""SELECT setval(pg_get_serial_sequence('modifier', 'modifierId'), (SELECT MAX("modifierId") FROM modifier));"""
184+
)
185+
# ### end Alembic commands ###

src/backend_api/app/alembic/versions/e38727349f3f_added_unidentified_aggregation_job.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
from app.alembic.replaceable_objects.main import ReplaceableTrigger
1515

16-
1716
# revision identifiers, used by Alembic.
1817
revision: str = "e38727349f3f"
1918
down_revision: Union[str, None] = "0f3f15f56b7d"
@@ -25,7 +24,7 @@
2524
"aggregate_unidentified",
2625
"unidentified_item",
2726
"""
28-
RETURNS TRIGGER AS $aggregate_unidentified$
27+
RETURNS TRIGGER AS ${name}$
2928
DECLARE
3029
current_hour INT;
3130
divine_id INT;
@@ -65,12 +64,12 @@
6564
6665
RETURN NEW;
6766
END;
68-
$aggregate_unidentified$ LANGUAGE plpgsql;
67+
${name}$ LANGUAGE plpgsql;
6968
""",
7069
"""
71-
BEFORE INSERT ON unidentified_item
70+
BEFORE INSERT ON {table}
7271
FOR EACH ROW
73-
EXECUTE FUNCTION aggregate_unidentified();
72+
EXECUTE FUNCTION {name}();
7473
""",
7574
)
7675

src/backend_api/app/api/routes/currency.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ async def create_currency(
135135

136136

137137
@router.put(
138-
"/{currencyId}",
138+
"/",
139139
response_model=schemas.Currency,
140140
dependencies=[
141141
Depends(get_current_active_superuser),
@@ -162,7 +162,7 @@ async def update_currency(
162162

163163

164164
@router.delete(
165-
"/{currencyId}",
165+
"/",
166166
response_model=str,
167167
dependencies=[
168168
Depends(get_current_active_superuser),

src/backend_api/app/api/routes/item_base_type.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ async def create_item_base_type(
113113

114114

115115
@router.put(
116-
"/{itemBaseTypeId}",
116+
"/",
117117
response_model=schemas.ItemBaseType,
118118
dependencies=[
119119
Depends(get_current_active_superuser),
@@ -141,7 +141,7 @@ async def update_item_base_type(
141141

142142

143143
@router.delete(
144-
"/{itemBaseTypeId}",
144+
"/",
145145
response_model=str,
146146
dependencies=[Depends(get_current_active_superuser)],
147147
)

src/backend_api/app/api/routes/modifier.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ async def create_modifier(
144144
)
145145
async def update_modifier(
146146
modifierId: int,
147+
position: int,
147148
modifier_update: schemas.ModifierUpdate,
148149
db: Session = Depends(get_db),
149150
):
@@ -155,7 +156,7 @@ async def update_modifier(
155156
Returns the updated modifier.
156157
"""
157158

158-
modifier_map = {"modifierId": modifierId}
159+
modifier_map = {"modifierId": modifierId, "position": position}
159160

160161
modifier = await CRUD_modifier.get(
161162
db=db,
@@ -172,6 +173,7 @@ async def update_modifier(
172173
)
173174
async def delete_modifier(
174175
modifierId: int,
176+
position: int,
175177
db: Session = Depends(get_db),
176178
):
177179
"""
@@ -181,7 +183,7 @@ async def delete_modifier(
181183
Always deletes one modifier.
182184
"""
183185

184-
modifier_map = {"modifierId": modifierId}
186+
modifier_map = {"modifierId": modifierId, "position": position}
185187
await CRUD_modifier.remove(db=db, filter=modifier_map)
186188

187189
return get_delete_return_msg(

0 commit comments

Comments
 (0)