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:
@ -7,6 +7,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
|
|
||||||
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
import camelCase from 'lodash.camelcase';
|
||||||
|
|
||||||
import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service';
|
import { ObjectMetadataService } from 'src/metadata/object-metadata/object-metadata.service';
|
||||||
import { FieldMetadataService } from 'src/metadata/field-metadata/field-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 =
|
const objectMetadataEntries =
|
||||||
await this.objectMetadataService.findManyWithinWorkspace(
|
await this.objectMetadataService.findManyWithinWorkspace(
|
||||||
[record.fromObjectMetadataId, record.toObjectMetadataId],
|
[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([
|
const createdFields = await this.fieldMetadataService.createMany([
|
||||||
// FROM
|
// FROM
|
||||||
{
|
{
|
||||||
@ -84,7 +100,9 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
|||||||
description: undefined,
|
description: undefined,
|
||||||
icon: record.toIcon,
|
icon: record.toIcon,
|
||||||
isCustom: true,
|
isCustom: true,
|
||||||
targetColumnMap: {},
|
targetColumnMap: {
|
||||||
|
value: foreignKeyColumnName,
|
||||||
|
},
|
||||||
isActive: true,
|
isActive: true,
|
||||||
type: FieldMetadataType.RELATION,
|
type: FieldMetadataType.RELATION,
|
||||||
objectMetadataId: record.toObjectMetadataId,
|
objectMetadataId: record.toObjectMetadataId,
|
||||||
@ -103,10 +121,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
|||||||
toFieldMetadataId: createdFieldMap[record.toObjectMetadataId].id,
|
toFieldMetadataId: createdFieldMap[record.toObjectMetadataId].id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const foreignKeyColumnName = `${
|
|
||||||
objectMetadataMap[record.fromObjectMetadataId].targetTableName
|
|
||||||
}Id`;
|
|
||||||
|
|
||||||
await this.tenantMigrationService.createCustomMigration(
|
await this.tenantMigrationService.createCustomMigration(
|
||||||
record.workspaceId,
|
record.workspaceId,
|
||||||
[
|
[
|
||||||
@ -133,6 +147,7 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
|||||||
referencedTableName:
|
referencedTableName:
|
||||||
objectMetadataMap[record.fromObjectMetadataId].targetTableName,
|
objectMetadataMap[record.fromObjectMetadataId].targetTableName,
|
||||||
referencedTableColumnName: 'id',
|
referencedTableColumnName: 'id',
|
||||||
|
isUnique: record.relationType === RelationMetadataType.ONE_TO_ONE,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -21,6 +21,7 @@ export type TenantMigrationColumnRelation = {
|
|||||||
columnName: string;
|
columnName: string;
|
||||||
referencedTableName: string;
|
referencedTableName: string;
|
||||||
referencedTableColumnName: string;
|
referencedTableColumnName: string;
|
||||||
|
isUnique?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TenantMigrationColumnAction = {
|
export type TenantMigrationColumnAction = {
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
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 { TenantMigrationService } from 'src/metadata/tenant-migration/tenant-migration.service';
|
||||||
import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service';
|
import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service';
|
||||||
@ -217,5 +223,16 @@ export class TenantMigrationRunnerService {
|
|||||||
onDelete: 'CASCADE',
|
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],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
// Otherwise it means it's a relation destination is of kind ONE
|
||||||
return `
|
return `
|
||||||
${fieldKey} {
|
${relationAlias} {
|
||||||
${this.fieldsStringFactory.createFieldsStringRecursive(
|
${this.fieldsStringFactory.createFieldsStringRecursive(
|
||||||
info,
|
info,
|
||||||
fieldValue,
|
fieldValue,
|
||||||
|
|||||||
Reference in New Issue
Block a user