|
5 | 5 |
|
6 | 6 | import { |
7 | 7 | FindOneOptions, |
8 | | - InsertQueryBuilder, |
9 | 8 | ObjectLiteral, |
10 | | - QueryRunner, |
11 | 9 | Repository, |
12 | | - SelectQueryBuilder, |
13 | 10 | } from 'typeorm'; |
14 | | -import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js'; |
15 | | -import { RelationCountLoader } from 'typeorm/query-builder/relation-count/RelationCountLoader.js'; |
16 | | -import { RelationIdLoader } from 'typeorm/query-builder/relation-id/RelationIdLoader.js'; |
17 | | -import { |
18 | | - RawSqlResultsToEntityTransformer, |
19 | | -} from 'typeorm/query-builder/transformer/RawSqlResultsToEntityTransformer.js'; |
20 | 11 | import { MiAbuseReportNotificationRecipient } from '@/models/AbuseReportNotificationRecipient.js'; |
21 | 12 | import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; |
22 | 13 | import { MiAccessToken } from '@/models/AccessToken.js'; |
@@ -96,66 +87,12 @@ import { MiWebhook } from '@/models/Webhook.js'; |
96 | 87 | import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; |
97 | 88 |
|
98 | 89 | export interface MiRepository<T extends ObjectLiteral> { |
99 | | - createTableColumnNames(this: Repository<T> & MiRepository<T>): string[]; |
100 | | - |
101 | 90 | insertOne(this: Repository<T> & MiRepository<T>, entity: QueryDeepPartialEntity<T>, findOptions?: Pick<FindOneOptions<T>, 'relations'>): Promise<T>; |
102 | | - |
103 | | - insertOneImpl(this: Repository<T> & MiRepository<T>, entity: QueryDeepPartialEntity<T>, findOptions?: Pick<FindOneOptions<T>, 'relations'>, queryRunner?: QueryRunner): Promise<T>; |
104 | | - |
105 | | - selectAliasColumnNames(this: Repository<T> & MiRepository<T>, queryBuilder: InsertQueryBuilder<T>, builder: SelectQueryBuilder<T>): void; |
106 | 91 | } |
107 | 92 |
|
108 | 93 | export const miRepository = { |
109 | | - createTableColumnNames() { |
110 | | - return this.metadata.columns.filter(column => column.isSelect && !column.isVirtual).map(column => column.databaseName); |
111 | | - }, |
112 | 94 | async insertOne(entity, findOptions?) { |
113 | | - const opt = this.manager.connection.options as PostgresConnectionOptions; |
114 | | - if (opt.replication) { |
115 | | - const queryRunner = this.manager.connection.createQueryRunner('master'); |
116 | | - try { |
117 | | - return this.insertOneImpl(entity, findOptions, queryRunner); |
118 | | - } finally { |
119 | | - await queryRunner.release(); |
120 | | - } |
121 | | - } else { |
122 | | - return this.insertOneImpl(entity, findOptions); |
123 | | - } |
124 | | - }, |
125 | | - async insertOneImpl(entity, findOptions?, queryRunner?) { |
126 | | - // ---- insert + returningの結果を共通テーブル式(CTE)に保持するクエリを生成 ---- |
127 | | - |
128 | | - const queryBuilder = this.createQueryBuilder().insert().values(entity); |
129 | | - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion |
130 | | - const mainAlias = queryBuilder.expressionMap.mainAlias!; |
131 | | - const name = mainAlias.name; |
132 | | - mainAlias.name = 't'; |
133 | | - const columnNames = this.createTableColumnNames(); |
134 | | - queryBuilder.returning(columnNames.reduce((a, c) => `${a}, ${queryBuilder.escape(c)}`, '').slice(2)); |
135 | | - |
136 | | - // ---- 共通テーブル式(CTE)から結果を取得 ---- |
137 | | - const builder = this.createQueryBuilder(undefined, queryRunner).addCommonTableExpression(queryBuilder, 'cte', { columnNames }); |
138 | | - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion |
139 | | - builder.expressionMap.mainAlias!.tablePath = 'cte'; |
140 | | - this.selectAliasColumnNames(queryBuilder, builder); |
141 | | - if (findOptions) { |
142 | | - builder.setFindOptions(findOptions); |
143 | | - } |
144 | | - const raw = await builder.execute(); |
145 | | - mainAlias.name = name; |
146 | | - const relationId = await new RelationIdLoader(builder.connection, this.queryRunner, builder.expressionMap.relationIdAttributes).load(raw); |
147 | | - const relationCount = await new RelationCountLoader(builder.connection, this.queryRunner, builder.expressionMap.relationCountAttributes).load(raw); |
148 | | - const result = new RawSqlResultsToEntityTransformer(builder.expressionMap, builder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, mainAlias); |
149 | | - return result[0]; |
150 | | - }, |
151 | | - selectAliasColumnNames(queryBuilder, builder) { |
152 | | - let selectOrAddSelect = (selection: string, selectionAliasName?: string) => { |
153 | | - selectOrAddSelect = (selection, selectionAliasName) => builder.addSelect(selection, selectionAliasName); |
154 | | - return builder.select(selection, selectionAliasName); |
155 | | - }; |
156 | | - for (const columnName of this.createTableColumnNames()) { |
157 | | - selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`); |
158 | | - } |
| 95 | + return await this.insert(entity).then(x => this.findOneOrFail({ where: x.identifiers[0], ...findOptions })); |
159 | 96 | }, |
160 | 97 | } satisfies MiRepository<ObjectLiteral>; |
161 | 98 |
|
|
0 commit comments