Skip to content

Commit b183dda

Browse files
author
Maggie Chen
committed
add migration file
1 parent 68299fa commit b183dda

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/* eslint-disable @typescript-eslint/naming-convention */
2+
import { DataType } from "sequelize-typescript";
3+
import { Migration } from "../umzug";
4+
5+
const USER_TABLE = "users";
6+
const APPLICANT_RECORDS_TABLE = "applicant_records";
7+
8+
const POSITION_TABLE = "positions";
9+
10+
const POSITION_DATA = [
11+
{ title: "Project Lead", department: "Engineering" },
12+
{ title: "Developer", department: "Engineering" },
13+
{ title: "VP Engineering", department: "Engineering" },
14+
{ title: "Designer", department: "Design" },
15+
{ title: "VP Design", department: "Design" },
16+
{ title: "Product Manager", department: "Product" },
17+
{ title: "VP Product", department: "Product" },
18+
{ title: "President", department: "Community" },
19+
{ title: "VP Scoping", department: "Community" },
20+
{ title: "VP Talent", department: "Community" },
21+
{ title: "VP Finance", department: "Community" },
22+
{ title: "Director Lead", department: "Community" },
23+
{ title: "Internal Director", department: "Community" },
24+
{ title: "External Director", department: "Community" },
25+
{ title: "Content Strategist", department: "Community" },
26+
{ title: "Graphic Designer", department: "Community" },
27+
];
28+
29+
const POSITION_TITLES = [
30+
"Project Lead",
31+
"Developer",
32+
"VP Engineering",
33+
"Designer",
34+
"VP Design",
35+
"Product Manager",
36+
"VP Product",
37+
"President",
38+
"VP Scoping",
39+
"VP Talent",
40+
"VP Finance",
41+
"Director Lead",
42+
"Internal Director",
43+
"External Director",
44+
"Content Strategist",
45+
"Graphic Designer",
46+
];
47+
48+
const DEPARTMENT_TITLES = ["Engineering", "Design", "Product", "Community"];
49+
50+
const position = "position";
51+
const enum_positions_title = "enum_positions_title";
52+
const enum_applicant_records_position = "enum_applicant_records_position";
53+
const enum_positions_department = "enum_positions_department";
54+
55+
export const up: Migration = async ({ context: sequelize }) => {
56+
// Drop FK constraints referencing positions
57+
await sequelize.getQueryInterface().sequelize.query(`
58+
ALTER TABLE "${USER_TABLE}" DROP CONSTRAINT IF EXISTS "${USER_TABLE}_${position}_fkey";
59+
ALTER TABLE "${APPLICANT_RECORDS_TABLE}" DROP CONSTRAINT IF EXISTS "${APPLICANT_RECORDS_TABLE}_${position}_fkey";
60+
`);
61+
62+
// Drop the enum-based positions table
63+
await sequelize.getQueryInterface().dropTable(POSITION_TABLE);
64+
65+
// Recreate positions table with string columns
66+
await sequelize.getQueryInterface().createTable(POSITION_TABLE, {
67+
title: {
68+
type: DataType.STRING,
69+
allowNull: false,
70+
primaryKey: true,
71+
},
72+
department: {
73+
type: DataType.STRING,
74+
allowNull: false,
75+
},
76+
});
77+
78+
// Re seed positions data
79+
await sequelize.getQueryInterface().bulkInsert(POSITION_TABLE, POSITION_DATA);
80+
81+
// Convert enum columns in users and applicant_records to type string
82+
await sequelize.getQueryInterface().sequelize.query(`
83+
ALTER TABLE "${USER_TABLE}"
84+
ALTER COLUMN "${position}" TYPE VARCHAR(255)
85+
USING ("${position}"::text);
86+
`);
87+
await sequelize.getQueryInterface().sequelize.query(`
88+
ALTER TABLE "${APPLICANT_RECORDS_TABLE}"
89+
ALTER COLUMN "${position}" TYPE VARCHAR(255)
90+
USING ("${position}"::text);
91+
`);
92+
93+
// Re add FKs referencing string positions.title
94+
await sequelize.getQueryInterface().sequelize.query(`
95+
ALTER TABLE "${USER_TABLE}"
96+
ADD CONSTRAINT "${USER_TABLE}_${position}_fkey"
97+
FOREIGN KEY ("${position}") REFERENCES "${POSITION_TABLE}" ("title")
98+
ON DELETE SET NULL ON UPDATE CASCADE;
99+
`);
100+
await sequelize.getQueryInterface().sequelize.query(`
101+
ALTER TABLE "${APPLICANT_RECORDS_TABLE}"
102+
ADD CONSTRAINT "${APPLICANT_RECORDS_TABLE}_${position}_fkey"
103+
FOREIGN KEY ("${position}") REFERENCES "${POSITION_TABLE}" ("title")
104+
ON DELETE SET NULL ON UPDATE CASCADE;
105+
`);
106+
107+
// Drop old enum types
108+
await sequelize
109+
.getQueryInterface()
110+
.sequelize.query(`DROP TYPE IF EXISTS "${enum_positions_title}" CASCADE;`);
111+
await sequelize
112+
.getQueryInterface()
113+
.sequelize.query(
114+
`DROP TYPE IF EXISTS "${enum_positions_department}}" CASCADE;`,
115+
);
116+
await sequelize
117+
.getQueryInterface()
118+
.sequelize.query(
119+
`DROP TYPE IF EXISTS "${enum_applicant_records_position}" CASCADE;`,
120+
);
121+
};
122+
123+
export const down: Migration = async ({ context: sequelize }) => {
124+
// Drop foreign key constraints referencing positions table
125+
await sequelize.getQueryInterface().sequelize.query(`
126+
ALTER TABLE "${USER_TABLE}" DROP CONSTRAINT IF EXISTS "${USER_TABLE}_${position}_fkey";
127+
ALTER TABLE "${APPLICANT_RECORDS_TABLE}" DROP CONSTRAINT IF EXISTS "${APPLICANT_RECORDS_TABLE}_${position}_fkey";
128+
`);
129+
130+
// Drop the string based positions table
131+
await sequelize.getQueryInterface().dropTable(POSITION_TABLE);
132+
133+
// Recreate table with enums
134+
await sequelize.getQueryInterface().createTable(POSITION_TABLE, {
135+
title: {
136+
type: DataType.ENUM(...POSITION_TITLES),
137+
allowNull: false,
138+
primaryKey: true,
139+
},
140+
department: {
141+
type: DataType.ENUM(...DEPARTMENT_TITLES),
142+
allowNull: false,
143+
},
144+
});
145+
146+
// Seed ENUM based positions table
147+
await sequelize.getQueryInterface().bulkInsert(POSITION_TABLE, POSITION_DATA);
148+
149+
// change column type from string to enum
150+
await sequelize.getQueryInterface().sequelize.query(`
151+
ALTER TABLE "users"
152+
ALTER COLUMN "position" TYPE "${enum_positions_title}"
153+
USING ("position"::text::"${enum_positions_title}");
154+
`);
155+
156+
// change column type from string to enum
157+
await sequelize.getQueryInterface().sequelize.query(`
158+
ALTER TABLE "applicant_records"
159+
ALTER COLUMN "position" TYPE "${enum_positions_title}"
160+
USING ("position"::text::"${enum_positions_title}");
161+
`);
162+
163+
// add back foreign keys
164+
await sequelize.getQueryInterface().sequelize.query(`
165+
ALTER TABLE "${USER_TABLE}"
166+
ADD CONSTRAINT "${USER_TABLE}_${position}_fkey"
167+
FOREIGN KEY ("${position}") REFERENCES "${POSITION_TABLE}" ("title")
168+
ON DELETE SET NULL ON UPDATE CASCADE;
169+
`);
170+
await sequelize.getQueryInterface().sequelize.query(`
171+
ALTER TABLE "${APPLICANT_RECORDS_TABLE}"
172+
ADD CONSTRAINT "${APPLICANT_RECORDS_TABLE}_${position}_fkey"
173+
FOREIGN KEY ("${position}") REFERENCES "${POSITION_TABLE}" ("title")
174+
ON DELETE SET NULL ON UPDATE CASCADE;
175+
`);
176+
};

0 commit comments

Comments
 (0)