fix: relations issues (#2497)

* fix: relations issues

one-to-one relation not working
alias should not be used on the foreignKey side

* fix: naming
This commit is contained in:
Jérémy M
2023-11-14 12:07:17 +01:00
committed by GitHub
parent 448f256a35
commit 65af954671
4 changed files with 50 additions and 7 deletions

View File

@ -7,6 +7,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
import { Repository } from 'typeorm';
import camelCase from 'lodash.camelcase';
import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service';
import { FieldMetadataService } from 'src/metadata/field-metadata/field-metadata.service';
@ -43,6 +44,19 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
);
}
/**
* Relation types
*
* MANY TO MANY:
* FROM Ǝ-E TO (NOT YET SUPPORTED)
*
* ONE TO MANY:
* FROM --E TO (host the id in the TO table)
*
* ONE TO ONE:
* FROM --- TO (host the id in the TO table)
*/
const objectMetadataEntries =
await this.objectMetadataService.findManyWithinWorkspace(
[record.fromObjectMetadataId, record.toObjectMetadataId],
@ -63,6 +77,8 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
);
}
const foreignKeyColumnName = `${camelCase(record.toName)}Id`;
const createdFields = await this.fieldMetadataService.createMany([
// FROM
{
@ -84,7 +100,9 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
description: undefined,
icon: record.toIcon,
isCustom: true,
targetColumnMap: {},
targetColumnMap: {
value: foreignKeyColumnName,
},
isActive: true,
type: FieldMetadataType.RELATION,
objectMetadataId: record.toObjectMetadataId,
@ -103,10 +121,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
toFieldMetadataId: createdFieldMap[record.toObjectMetadataId].id,
});
const foreignKeyColumnName = `${
objectMetadataMap[record.fromObjectMetadataId].targetTableName
}Id`;
await this.tenantMigrationService.createCustomMigration(
record.workspaceId,
[
@ -133,6 +147,7 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
referencedTableName:
objectMetadataMap[record.fromObjectMetadataId].targetTableName,
referencedTableColumnName: 'id',
isUnique: record.relationType === RelationMetadataType.ONE_TO_ONE,
},
],
},

View File

@ -21,6 +21,7 @@ export type TenantMigrationColumnRelation = {
columnName: string;
referencedTableName: string;
referencedTableColumnName: string;
isUnique?: boolean;
};
export type TenantMigrationColumnAction = {

View File

@ -1,6 +1,12 @@
import { Injectable } from '@nestjs/common';
import { QueryRunner, Table, TableColumn, TableForeignKey } from 'typeorm';
import {
QueryRunner,
Table,
TableColumn,
TableForeignKey,
TableUnique,
} from 'typeorm';
import { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service';
import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service';
@ -217,5 +223,16 @@ export class TenantMigrationRunnerService {
onDelete: 'CASCADE',
}),
);
// Create unique constraint if for one to one relation
if (migrationColumn.isUnique) {
await queryRunner.createUniqueConstraint(
`${schemaName}.${tableName}`,
new TableUnique({
name: `UNIQUE_${tableName}_${migrationColumn.columnName}`,
columnNames: [migrationColumn.columnName],
}),
);
}
}
}

View File

@ -95,10 +95,20 @@ export class CompositeFieldAliasFactory {
}
`;
}
let relationAlias = fieldKey;
// For one to one relations, pg_graphql use the targetTableName on the side that is not storing the foreign key
// so we need to alias it to the field key
if (
relationMetadata.relationType === RelationMetadataType.ONE_TO_ONE &&
relationDirection === RelationDirection.FROM
) {
relationAlias = `${fieldKey}: ${referencedObjectMetadata.targetTableName}`;
}
// Otherwise it means it's a relation destination is of kind ONE
return `
${fieldKey} {
${relationAlias} {
${this.fieldsStringFactory.createFieldsStringRecursive(
info,
fieldValue,