Skip to content

Commit

Permalink
fix: create the migrations for the conversion of tables to ulid
Browse files Browse the repository at this point in the history
Every text id in the database will need to be converted to the new
`ulid` type once the extensiion allows for joins. This conversion set
will update all of the types, and set up the defaults to be the new
`gen_ulid` method that the extension provides.

Once everything is in working order, I'll create another migration that
drops the original `ulid()` function I was working with.
  • Loading branch information
jmcdo29 committed Jul 22, 2023
1 parent 6395cdd commit e1ff84d
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 5 deletions.
1 change: 1 addition & 0 deletions libs/db/migrations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ erDiagram
string type
}
Deity_Domain {
ulid id
ulid deity_id
ulid domain_id
}
Expand Down
1 change: 1 addition & 0 deletions libs/db/migrations/diagram.mmd
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ erDiagram
string type
}
Deity_Domain {
ulid id
ulid deity_id
ulid domain_id
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import {
AlterColumnBuilder,
AlterColumnBuilderCallback,
Kysely,
sql,
} from 'kysely';

const convertToUlid = (
column: string
): [string, AlterColumnBuilderCallback] => [
column,
(col: AlterColumnBuilder) =>
col.setDataType(sql`ulid USING (${column}::ulid)`),
];

const setUlidDefault = (
column: string
): [string, AlterColumnBuilderCallback] => [
column,
(col: AlterColumnBuilder) => col.setDefault(sql`gen_ulid()`),
];

const migrateTableColumnToUlid = async (
db: Kysely<any>,
table: string,
column: string,
setDefault = false
): Promise<void> => {
let command = db.schema
.alterTable(table)
.alterColumn(...convertToUlid(column));
if (setDefault) {
command = command.alterColumn(...setUlidDefault(column));
}
await command.execute();
};

const recreateForeignKey = async (
db: Kysely<any>,
table: string,
column: string,
targetTable: string,
targetColumn: string
): Promise<void> => {
await db.schema
.alterTable(table)
.addForeignKeyConstraint(`${table}_${column}_fkey`, [column], targetTable, [
targetColumn,
])
.execute();
};

export const up = async (db: Kysely<any>): Promise<void> => {
await sql`CREATE EXTENSION ulid;`.execute(db);
await db.schema
.alterTable('deity_domain')
.dropConstraint('deity_domain_deity_id_fkey')
.execute();
await db.schema
.alterTable('deity_domain')
.dropConstraint('deity_domain_domain_id_fkey')
.execute();
await migrateTableColumnToUlid(db, 'domain', 'id', true);
await migrateTableColumnToUlid(db, 'deity', 'id', true);
await migrateTableColumnToUlid(db, 'deity_domain', 'id', true);
await migrateTableColumnToUlid(db, 'deity_domain', 'deity_id');
await migrateTableColumnToUlid(db, 'deity_domain', 'domain_id');
await recreateForeignKey(db, 'deity_domain', 'deity_id', 'deity', 'id');
await recreateForeignKey(db, 'deity_domain', 'domain_id', 'domain', 'id');
await db.schema
.alterTable('deity')
.dropConstraint('deity_category_fkey')
.execute();
await db.schema
.alterTable('detiy')
.dropConstraint('deity_location_fkey')
.execute();
await migrateTableColumnToUlid(db, 'deity_category', 'id', true);
await migrateTableColumnToUlid(db, 'deity', 'category');
await migrateTableColumnToUlid(db, 'deity', 'location');
await recreateForeignKey(db, 'deity', 'category', 'deity_category', 'id');
await migrateTableColumnToUlid(db, 'location', 'id', true);
await recreateForeignKey(db, 'deity', 'location', 'location', 'id');
await db.schema
.alterTable('racial_ability')
.dropConstraint('racial_ability_race_id_fkey')
.execute();
await migrateTableColumnToUlid(db, 'race', 'id', true);
await migrateTableColumnToUlid(db, 'racial_ability', 'id', true);
await migrateTableColumnToUlid(db, 'racial_ability', 'race_id');
await recreateForeignKey(db, 'racial_ability', 'race_id', 'race', 'id');
await db.schema
.alterTable('user_permission')
.dropConstraint('user_permission_role_id_fkey')
.execute();
await db.schema
.alterTable('user_permission')
.dropConstraint('user_permission_user_id_fkey')
.execute();
await db.schema
.alterTable('login_method')
.dropConstraint('login_method_user_id_fkey')
.execute();
await db.schema
.alterTable('local_login')
.dropConstraint('local_login_login_method_id_fkey')
.execute();
await migrateTableColumnToUlid(db, 'role', 'id', true);
await migrateTableColumnToUlid(db, 'local_login', 'id', true);
await migrateTableColumnToUlid(db, 'local_login', 'login_method_id');
await migrateTableColumnToUlid(db, 'login_method', 'id', true);
await migrateTableColumnToUlid(db, 'login_method', 'user_id');
await migrateTableColumnToUlid(db, 'user_account', 'id', true);
await migrateTableColumnToUlid(db, 'user_permission', 'id', true);
await migrateTableColumnToUlid(db, 'user_permission', 'user_id');
await migrateTableColumnToUlid(db, 'user_permission', 'role_id');
await recreateForeignKey(db, 'user_permission', 'role_id', 'role', 'id');
await recreateForeignKey(
db,
'user_permission',
'user_id',
'user_account',
'id'
);
await recreateForeignKey(db, 'login_method', 'user_id', 'user_account', 'id');
await recreateForeignKey(
db,
'local_login',
'login_method_id',
'login_method',
'id'
);
};

export const down = async (db: Kysely<any>) => {
await sql`DROP EXTENSION ulid`.execute(db);
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"argon2": "^0.30.3",
"axios": "^1.0.0",
"jotai": "^2.2.2",
"kysely": "^0.24.2",
"kysely": "^0.26.1",
"nest-commander": "^3.9.0",
"nest-cookies": "^1.3.0",
"nodemailer": "^6.9.3",
Expand Down
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e1ff84d

Please sign in to comment.