Files
twenty/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service.ts
Marie 4bd0aafb8e [fix] Update remote table sync status in cache after schema update (#5553)
Upon schema update, sync status can change from synced to non_synced in
case the update regards a table that was deleted. Let's update the sync
status too to avoid displaying the table as still synchronized.


https://github.com/twentyhq/twenty/assets/51697796/7ff2342b-ce9f-4179-9b76-940617cf1292
2024-05-24 10:20:08 +02:00

126 lines
4.0 KiB
TypeScript

import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { EntityManager, Repository } from 'typeorm';
import { v4 } from 'uuid';
import {
RemoteServerEntity,
RemoteServerType,
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table';
import { STRIPE_DISTANT_TABLES } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/utils/stripe-distant-tables.util';
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
@Injectable()
export class DistantTableService {
constructor(
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
@InjectRepository(RemoteServerEntity, 'metadata')
private readonly remoteServerRepository: Repository<
RemoteServerEntity<RemoteServerType>
>,
) {}
public async fetchDistantTables(
remoteServer: RemoteServerEntity<RemoteServerType>,
workspaceId: string,
tableName?: string,
): Promise<DistantTables> {
if (remoteServer.schema) {
return this.getDistantTablesFromDynamicSchema(
remoteServer,
workspaceId,
tableName,
);
}
return this.getDistantTablesFromStaticSchema(remoteServer);
}
public async getDistantTableColumns(
remoteServer: RemoteServerEntity<RemoteServerType>,
workspaceId: string,
tableName: string,
): Promise<PostgresTableSchemaColumn[]> {
const distantTables = await this.fetchDistantTables(
remoteServer,
workspaceId,
tableName,
);
return distantTables[tableName];
}
private async getDistantTablesFromDynamicSchema(
remoteServer: RemoteServerEntity<RemoteServerType>,
workspaceId: string,
tableName?: string,
): Promise<DistantTables> {
if (!remoteServer.schema) {
throw new BadRequestException('Remote server schema is not defined');
}
const tmpSchemaId = v4();
const tmpSchemaName = `${workspaceId}_${remoteServer.id}_${tmpSchemaId}`;
const workspaceDataSource =
await this.workspaceDataSourceService.connectToWorkspaceDataSource(
workspaceId,
);
const distantTables = await workspaceDataSource.transaction(
async (entityManager: EntityManager) => {
await entityManager.query(`CREATE SCHEMA "${tmpSchemaName}"`);
const tableLimitationsOptions = tableName
? ` LIMIT TO ("${tableName}")`
: '';
await entityManager.query(
`IMPORT FOREIGN SCHEMA "${remoteServer.schema}"${tableLimitationsOptions} FROM SERVER "${remoteServer.foreignDataWrapperId}" INTO "${tmpSchemaName}"`,
);
const createdForeignTableNames = await entityManager.query(
`SELECT table_name, column_name, data_type, udt_name FROM information_schema.columns WHERE table_schema = '${tmpSchemaName}'`,
);
await entityManager.query(`DROP SCHEMA "${tmpSchemaName}" CASCADE`);
return createdForeignTableNames.reduce(
(acc, { table_name, column_name, data_type, udt_name }) => {
if (!acc[table_name]) {
acc[table_name] = [];
}
acc[table_name].push({
columnName: column_name,
dataType: data_type,
udtName: udt_name,
});
return acc;
},
{},
);
},
);
return distantTables;
}
private async getDistantTablesFromStaticSchema(
remoteServer: RemoteServerEntity<RemoteServerType>,
): Promise<DistantTables> {
switch (remoteServer.foreignDataWrapperType) {
case RemoteServerType.STRIPE_FDW:
return STRIPE_DISTANT_TABLES;
default:
throw new BadRequestException(
`Type ${remoteServer.foreignDataWrapperType} does not have a static schema.`,
);
}
}
}