chore(backend): override createJoinExpression

This commit is contained in:
Acid Chicken (硫酸鶏) 2024-05-30 17:09:46 +09:00
parent 907fc5a462
commit cbc806e61d
No known key found for this signature in database
GPG Key ID: 3E87B98A3F6BAB99
1 changed files with 55 additions and 13 deletions

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository, SelectQueryBuilder } from 'typeorm';
import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository, SelectQueryBuilder, TypeORMError } from 'typeorm';
import { DriverUtils } from 'typeorm/driver/DriverUtils.js';
import { RelationCountLoader } from 'typeorm/query-builder/relation-count/RelationCountLoader.js';
import { RelationIdLoader } from 'typeorm/query-builder/relation-id/RelationIdLoader.js';
@ -114,19 +114,61 @@ export const miRepository = {
this.selectAliasColumnNames(queryBuilder, builder);
if (findOptions) {
builder.setFindOptions(findOptions);
/*
// @ts-expect-error -- protected
builder.findOptions = findOptions;
if (findOptions.relations) {
const relations = Array.isArray(findOptions.relations) ? OrmUtils.propertyPathsToTruthyObject(findOptions.relations) : findOptions.relations;
// @ts-expect-error -- protected
builder.buildRelations(relations, undefined, mainAlias.metadata, mainAlias.name);
}
// @ts-expect-error -- protected
for (const join of builder.joins) {
}
*/
console.log(builder.expressionMap.joinAttributes);
builder.createJoinExpression = function(this: SelectQueryBuilder<ObjectLiteral>) {
const joins = this.expressionMap.joinAttributes.map((joinAttr) => {
/* eslint-disable @typescript-eslint/no-non-null-assertion */
const relation = joinAttr.relation!;
const destinationTableName = joinAttr.tablePath;
const destinationTableAlias = joinAttr.alias.name;
let appendedCondition = joinAttr.condition ? ` AND (${joinAttr.condition})` : '';
const parentAlias = joinAttr.parentAlias;
if (relation.isManyToOne || relation.isOneToOneOwner) {
// JOIN `category` `category` ON `category`.`id` = `post`.`categoryId`
const condition = relation.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${relation.propertyPath}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND ');
return ` ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${
// @ts-expect-error -- private
this.createTableLockExpression()
} ON ${this.replacePropertyNames(condition + appendedCondition)}`;
} else if (relation.isOneToMany || relation.isOneToOneNotOwner) {
// JOIN `post` `post` ON `post`.`categoryId` = `category`.`id`
const condition = relation.inverseRelation!.joinColumns.map((joinColumn) => {
if (relation.inverseEntityMetadata.tableType === 'entity-child' && relation.inverseEntityMetadata.discriminatorColumn) {
appendedCondition += ` AND ${destinationTableAlias}.${relation.inverseEntityMetadata.discriminatorColumn.databaseName}='${relation.inverseEntityMetadata.discriminatorValue}'`;
}
return `${destinationTableAlias}.${relation.inverseRelation!.propertyPath}.${joinColumn.referencedColumn!.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`;
}).join(' AND ');
if (!condition) {
throw new TypeORMError(`Relation ${relation.entityMetadata.name}.${relation.propertyName} does not have join columns.`);
}
return ` ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${
// @ts-expect-error -- private
this.createTableLockExpression()
} ON ${this.replacePropertyNames(condition + appendedCondition)}`;
} else {
// means many-to-many
const junctionTableName = relation.junctionEntityMetadata!.tablePath;
const junctionAlias = joinAttr.junctionAlias;
let junctionCondition = '', destinationCondition = '';
if (relation.isOwning) {
junctionCondition = relation.joinColumns.map((joinColumn) => `${junctionAlias}.${joinColumn.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND ');
destinationCondition = relation.inverseJoinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${junctionAlias}_${joinColumn.propertyPath}`).join(' AND ');
} else {
junctionCondition = relation.inverseRelation!.inverseJoinColumns.map((joinColumn) => `${junctionAlias}.${joinColumn.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND ');
destinationCondition = relation.inverseRelation!.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${junctionAlias}_${joinColumn.propertyPath}`).join(' AND ');
}
return ` ${joinAttr.direction} JOIN ${this.getTableName(junctionTableName)} ${this.escape(junctionAlias)}${
// @ts-expect-error -- private
this.createTableLockExpression()
} ON ${this.replacePropertyNames(junctionCondition)} ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${
// @ts-expect-error -- private
this.createTableLockExpression()
} ON ${this.replacePropertyNames(destinationCondition + appendedCondition)}`;
}
/* eslint-enable @typescript-eslint/no-non-null-assertion */
});
return joins.join(' ');
};
}
const [query, parameters] = builder.getQueryAndParameters();
for (let i = 0; i < Math.ceil(query.length / 10000); i++) {