Handle relations separately for remotes (#5538)
Remote object id columns are not removed anymore when a remote object is unsynced. This is because we do not use relations anymore. We only created the id field. So the current behavior that was implemented for custom objects, to retrieve the fields to deleted, does not work. Since remote object relations are really different, I extracted the logic from `objectMetadataService`. It now handles only the relations for custom objects creation and deletion (this part should be extracted as well). I create a new remote table relation service that will: - fetch objects metadata linked to remotes (favorites, activityTargets...) - look for columns based on remote object name - delete the fields and columns
This commit is contained in:
@ -1,76 +0,0 @@
|
||||
import { buildAlteredCommentOnForeignKeyDeletion } from 'src/engine/metadata-modules/object-metadata/utils/create-migration-for-foreign-key-comment-alteration.util';
|
||||
|
||||
describe('buildAlteredCommentOnForeignKeyDeletion', () => {
|
||||
const localObjectMetadataName = 'favorite';
|
||||
const remoteObjectMetadataName = 'blog';
|
||||
const schema = 'schema';
|
||||
const workspaceDataSource = {
|
||||
query: jest.fn(),
|
||||
};
|
||||
|
||||
it('should return null if no comment ', async () => {
|
||||
workspaceDataSource.query.mockResolvedValueOnce([]);
|
||||
|
||||
const result = await buildAlteredCommentOnForeignKeyDeletion(
|
||||
localObjectMetadataName,
|
||||
remoteObjectMetadataName,
|
||||
schema,
|
||||
workspaceDataSource as any,
|
||||
);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null if the existing comment does not contain foreign keys', async () => {
|
||||
workspaceDataSource.query.mockResolvedValueOnce([
|
||||
{ col_description: '@graphql({"totalCount":{"enabled":true}})' },
|
||||
]);
|
||||
|
||||
const result = await buildAlteredCommentOnForeignKeyDeletion(
|
||||
localObjectMetadataName,
|
||||
remoteObjectMetadataName,
|
||||
schema,
|
||||
workspaceDataSource as any,
|
||||
);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return altered comment without foreign key', async () => {
|
||||
const existingComment = {
|
||||
col_description: `@graphql({"totalCount":{"enabled":true},"foreign_keys":[{"local_name":"favoriteCollection","local_columns":["${remoteObjectMetadataName}Id"],"foreign_name":"${remoteObjectMetadataName}","foreign_schema":"schema","foreign_table":"${remoteObjectMetadataName}","foreign_columns":["id"]}]})`,
|
||||
};
|
||||
|
||||
workspaceDataSource.query.mockResolvedValueOnce([existingComment]);
|
||||
|
||||
const result = await buildAlteredCommentOnForeignKeyDeletion(
|
||||
localObjectMetadataName,
|
||||
remoteObjectMetadataName,
|
||||
schema,
|
||||
workspaceDataSource as any,
|
||||
);
|
||||
|
||||
expect(result).toBe(
|
||||
'@graphql({"totalCount":{"enabled":true},"foreign_keys":[]})',
|
||||
);
|
||||
});
|
||||
|
||||
it('should return altered comment without the input foreign key', async () => {
|
||||
const existingComment = {
|
||||
col_description: `@graphql({"totalCount":{"enabled":true},"foreign_keys":[{"local_name":"favoriteCollection","local_columns":["${remoteObjectMetadataName}Id"],"foreign_name":"${remoteObjectMetadataName}","foreign_schema":"schema","foreign_table":"${remoteObjectMetadataName}","foreign_columns":["id"]}, {"local_name":"favoriteCollection","local_columns":["testId"],"foreign_name":"test","foreign_schema":"schema","foreign_table":"test","foreign_columns":["id"]}]})`,
|
||||
};
|
||||
|
||||
workspaceDataSource.query.mockResolvedValueOnce([existingComment]);
|
||||
|
||||
const result = await buildAlteredCommentOnForeignKeyDeletion(
|
||||
localObjectMetadataName,
|
||||
remoteObjectMetadataName,
|
||||
schema,
|
||||
workspaceDataSource as any,
|
||||
);
|
||||
|
||||
expect(result).toBe(
|
||||
'@graphql({"totalCount":{"enabled":true},"foreign_keys":[{"local_name":"favoriteCollection","local_columns":["testId"],"foreign_name":"test","foreign_schema":"schema","foreign_table":"test","foreign_columns":["id"]}]})',
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -9,7 +9,7 @@ import {
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||
|
||||
export const createWorkspaceMigrationsForCustomObjectRelations = (
|
||||
export const buildMigrationsForCustomObjectRelations = (
|
||||
createdObjectMetadata: ObjectMetadataEntity,
|
||||
activityTargetObjectMetadata: ObjectMetadataEntity,
|
||||
attachmentObjectMetadata: ObjectMetadataEntity,
|
||||
@ -1,97 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { RelationToDelete } from 'src/engine/metadata-modules/relation-metadata/types/relation-to-delete';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
WorkspaceMigrationTableActionType,
|
||||
WorkspaceMigrationColumnActionType,
|
||||
WorkspaceMigrationCreateComment,
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
|
||||
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
|
||||
|
||||
export const buildAlteredCommentOnForeignKeyDeletion = async (
|
||||
localObjectMetadataName: string,
|
||||
remoteObjectMetadataName: string,
|
||||
schema: string,
|
||||
workspaceDataSource: DataSource | undefined,
|
||||
): Promise<string | null> => {
|
||||
const existingComment = await workspaceDataSource?.query(
|
||||
`SELECT col_description('${schema}."${localObjectMetadataName}"'::regclass, 0)`,
|
||||
);
|
||||
|
||||
if (!existingComment[0]?.col_description) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const commentWithoutGraphQL = existingComment[0].col_description
|
||||
.replace('@graphql(', '')
|
||||
.replace(')', '');
|
||||
|
||||
const parsedComment = JSON.parse(commentWithoutGraphQL);
|
||||
|
||||
const currentForeignKeys = parsedComment.foreign_keys;
|
||||
|
||||
if (!currentForeignKeys) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const updatedForeignKeys = currentForeignKeys.filter(
|
||||
(foreignKey: any) =>
|
||||
foreignKey.foreign_name !== remoteObjectMetadataName &&
|
||||
foreignKey.foreign_table !== remoteObjectMetadataName,
|
||||
);
|
||||
|
||||
parsedComment.foreign_keys = updatedForeignKeys;
|
||||
|
||||
return `@graphql(${JSON.stringify(parsedComment)})`;
|
||||
};
|
||||
|
||||
export const createMigrationToAlterCommentOnForeignKeyDeletion = async (
|
||||
dataSourceService: DataSourceService,
|
||||
typeORMService: TypeORMService,
|
||||
workspaceMigrationService: WorkspaceMigrationService,
|
||||
workspaceId: string,
|
||||
relationToDelete: RelationToDelete,
|
||||
) => {
|
||||
const dataSourceMetadata =
|
||||
await dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const workspaceDataSource =
|
||||
await typeORMService.connectToDataSource(dataSourceMetadata);
|
||||
|
||||
const alteredComment = await buildAlteredCommentOnForeignKeyDeletion(
|
||||
relationToDelete.toObjectName,
|
||||
relationToDelete.fromObjectName,
|
||||
dataSourceMetadata.schema,
|
||||
workspaceDataSource,
|
||||
);
|
||||
|
||||
if (alteredComment) {
|
||||
await workspaceMigrationService.createCustomMigration(
|
||||
generateMigrationName(
|
||||
`alter-comment-${relationToDelete.fromObjectName}-${relationToDelete.toObjectName}`,
|
||||
),
|
||||
workspaceId,
|
||||
[
|
||||
{
|
||||
name: computeTableName(
|
||||
relationToDelete.toObjectName,
|
||||
relationToDelete.toObjectMetadataIsCustom,
|
||||
),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE_COMMENT,
|
||||
comment: alteredComment,
|
||||
} satisfies WorkspaceMigrationCreateComment,
|
||||
],
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -1,77 +0,0 @@
|
||||
import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
WorkspaceMigrationTableAction,
|
||||
WorkspaceMigrationColumnActionType,
|
||||
WorkspaceMigrationColumnCreate,
|
||||
WorkspaceMigrationTableActionType,
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||
|
||||
export const createWorkspaceMigrationsForRemoteObjectRelations = async (
|
||||
createdObjectMetadata: ObjectMetadataEntity,
|
||||
activityTargetObjectMetadata: ObjectMetadataEntity,
|
||||
attachmentObjectMetadata: ObjectMetadataEntity,
|
||||
timelineActivityObjectMetadata: ObjectMetadataEntity,
|
||||
favoriteObjectMetadata: ObjectMetadataEntity,
|
||||
primaryKeyColumnType: string,
|
||||
): Promise<WorkspaceMigrationTableAction[]> => {
|
||||
return [
|
||||
{
|
||||
name: computeObjectTargetTable(activityTargetObjectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE,
|
||||
columnName: computeColumnName(createdObjectMetadata.nameSingular, {
|
||||
isForeignKey: true,
|
||||
}),
|
||||
columnType: primaryKeyColumnType,
|
||||
isNullable: true,
|
||||
} satisfies WorkspaceMigrationColumnCreate,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: computeObjectTargetTable(attachmentObjectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE,
|
||||
columnName: computeColumnName(createdObjectMetadata.nameSingular, {
|
||||
isForeignKey: true,
|
||||
}),
|
||||
columnType: primaryKeyColumnType,
|
||||
isNullable: true,
|
||||
} satisfies WorkspaceMigrationColumnCreate,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: computeObjectTargetTable(timelineActivityObjectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE,
|
||||
columnName: computeColumnName(createdObjectMetadata.nameSingular, {
|
||||
isForeignKey: true,
|
||||
}),
|
||||
columnType: primaryKeyColumnType,
|
||||
isNullable: true,
|
||||
} satisfies WorkspaceMigrationColumnCreate,
|
||||
],
|
||||
},
|
||||
{
|
||||
name: computeObjectTargetTable(favoriteObjectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE,
|
||||
columnName: computeColumnName(createdObjectMetadata.nameSingular, {
|
||||
isForeignKey: true,
|
||||
}),
|
||||
columnType: primaryKeyColumnType,
|
||||
isNullable: true,
|
||||
} satisfies WorkspaceMigrationColumnCreate,
|
||||
],
|
||||
},
|
||||
];
|
||||
};
|
||||
Reference in New Issue
Block a user