Minor refacto and fixes on Remotes updates (#5438)
In this PR - Code refactoring - v0 of adding "updates available" info in Connection sync status <img width="835" alt="Capture d’écran 2024-05-16 à 17 02 07" src="https://github.com/twentyhq/twenty/assets/51697796/9674d3ca-bed2-4520-a5a6-ba37bc242d06"> - fix distant table columns with not-camel case names are always considered as new
This commit is contained in:
@ -250,6 +250,14 @@ export type DeleteOneRelationInput = {
|
|||||||
id: Scalars['UUID']['input'];
|
id: Scalars['UUID']['input'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Schema update on a table */
|
||||||
|
export enum DistantTableUpdate {
|
||||||
|
ColumnsAdded = 'COLUMNS_ADDED',
|
||||||
|
ColumnsDeleted = 'COLUMNS_DELETED',
|
||||||
|
ColumnsTypeChanged = 'COLUMNS_TYPE_CHANGED',
|
||||||
|
TableDeleted = 'TABLE_DELETED'
|
||||||
|
}
|
||||||
|
|
||||||
export type EmailPasswordResetLink = {
|
export type EmailPasswordResetLink = {
|
||||||
__typename?: 'EmailPasswordResetLink';
|
__typename?: 'EmailPasswordResetLink';
|
||||||
/** Boolean that confirms query was dispatched */
|
/** Boolean that confirms query was dispatched */
|
||||||
@ -330,8 +338,6 @@ export enum FileFolder {
|
|||||||
export type FindManyRemoteTablesInput = {
|
export type FindManyRemoteTablesInput = {
|
||||||
/** The id of the remote server. */
|
/** The id of the remote server. */
|
||||||
id: Scalars['ID']['input'];
|
id: Scalars['ID']['input'];
|
||||||
/** Indicates if data from distant tables should be refreshed. */
|
|
||||||
refreshData?: InputMaybe<Scalars['Boolean']['input']>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FullName = {
|
export type FullName = {
|
||||||
@ -812,7 +818,7 @@ export type RemoteTable = {
|
|||||||
id?: Maybe<Scalars['UUID']['output']>;
|
id?: Maybe<Scalars['UUID']['output']>;
|
||||||
name: Scalars['String']['output'];
|
name: Scalars['String']['output'];
|
||||||
schema?: Maybe<Scalars['String']['output']>;
|
schema?: Maybe<Scalars['String']['output']>;
|
||||||
schemaPendingUpdates?: Maybe<Array<TableUpdate>>;
|
schemaPendingUpdates?: Maybe<Array<DistantTableUpdate>>;
|
||||||
status: RemoteTableStatus;
|
status: RemoteTableStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -857,14 +863,6 @@ export type Support = {
|
|||||||
supportFrontChatId?: Maybe<Scalars['String']['output']>;
|
supportFrontChatId?: Maybe<Scalars['String']['output']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Schema update on a table */
|
|
||||||
export enum TableUpdate {
|
|
||||||
ColumnsAdded = 'COLUMNS_ADDED',
|
|
||||||
ColumnsDeleted = 'COLUMNS_DELETED',
|
|
||||||
ColumnsTypeChanged = 'COLUMNS_TYPE_CHANGED',
|
|
||||||
TableDeleted = 'TABLE_DELETED'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Telemetry = {
|
export type Telemetry = {
|
||||||
__typename?: 'Telemetry';
|
__typename?: 'Telemetry';
|
||||||
anonymizationEnabled: Scalars['Boolean']['output'];
|
anonymizationEnabled: Scalars['Boolean']['output'];
|
||||||
@ -1261,7 +1259,7 @@ export type RelationEdge = {
|
|||||||
|
|
||||||
export type RemoteServerFieldsFragment = { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null };
|
export type RemoteServerFieldsFragment = { __typename?: 'RemoteServer', id: string, createdAt: any, foreignDataWrapperId: string, foreignDataWrapperOptions?: any | null, foreignDataWrapperType: string, updatedAt: any, schema?: string | null, userMappingOptions?: { __typename?: 'UserMappingOptionsUser', user?: string | null } | null };
|
||||||
|
|
||||||
export type RemoteTableFieldsFragment = { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<TableUpdate> | null };
|
export type RemoteTableFieldsFragment = { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<DistantTableUpdate> | null };
|
||||||
|
|
||||||
export type CreateServerMutationVariables = Exact<{
|
export type CreateServerMutationVariables = Exact<{
|
||||||
input: CreateRemoteServerInput;
|
input: CreateRemoteServerInput;
|
||||||
@ -1282,14 +1280,14 @@ export type SyncRemoteTableMutationVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type SyncRemoteTableMutation = { __typename?: 'Mutation', syncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<TableUpdate> | null } };
|
export type SyncRemoteTableMutation = { __typename?: 'Mutation', syncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<DistantTableUpdate> | null } };
|
||||||
|
|
||||||
export type UnsyncRemoteTableMutationVariables = Exact<{
|
export type UnsyncRemoteTableMutationVariables = Exact<{
|
||||||
input: RemoteTableInput;
|
input: RemoteTableInput;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type UnsyncRemoteTableMutation = { __typename?: 'Mutation', unsyncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<TableUpdate> | null } };
|
export type UnsyncRemoteTableMutation = { __typename?: 'Mutation', unsyncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<DistantTableUpdate> | null } };
|
||||||
|
|
||||||
export type UpdateServerMutationVariables = Exact<{
|
export type UpdateServerMutationVariables = Exact<{
|
||||||
input: UpdateRemoteServerInput;
|
input: UpdateRemoteServerInput;
|
||||||
@ -1310,7 +1308,7 @@ export type GetManyRemoteTablesQueryVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type GetManyRemoteTablesQuery = { __typename?: 'Query', findAvailableRemoteTablesByServerId: Array<{ __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<TableUpdate> | null }> };
|
export type GetManyRemoteTablesQuery = { __typename?: 'Query', findAvailableRemoteTablesByServerId: Array<{ __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array<DistantTableUpdate> | null }> };
|
||||||
|
|
||||||
export type GetOneDatabaseConnectionQueryVariables = Exact<{
|
export type GetOneDatabaseConnectionQueryVariables = Exact<{
|
||||||
input: RemoteServerIdInput;
|
input: RemoteServerIdInput;
|
||||||
|
|||||||
@ -10,13 +10,11 @@ import {
|
|||||||
type UseGetDatabaseConnectionTablesParams = {
|
type UseGetDatabaseConnectionTablesParams = {
|
||||||
connectionId: string;
|
connectionId: string;
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
refreshData?: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useGetDatabaseConnectionTables = ({
|
export const useGetDatabaseConnectionTables = ({
|
||||||
connectionId,
|
connectionId,
|
||||||
skip,
|
skip,
|
||||||
refreshData,
|
|
||||||
}: UseGetDatabaseConnectionTablesParams) => {
|
}: UseGetDatabaseConnectionTablesParams) => {
|
||||||
const apolloMetadataClient = useApolloMetadataClient();
|
const apolloMetadataClient = useApolloMetadataClient();
|
||||||
|
|
||||||
@ -29,7 +27,6 @@ export const useGetDatabaseConnectionTables = ({
|
|||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
id: connectionId,
|
id: connectionId,
|
||||||
refreshData: refreshData,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -25,13 +25,23 @@ export const SettingsIntegrationDatabaseConnectionSyncStatus = ({
|
|||||||
(table) => table.status === RemoteTableStatus.Synced,
|
(table) => table.status === RemoteTableStatus.Synced,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const updatesAvailable = tables.some(
|
||||||
|
(table) =>
|
||||||
|
table.schemaPendingUpdates?.length &&
|
||||||
|
table.schemaPendingUpdates.length > 0,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Status
|
<Status
|
||||||
color="green"
|
color={updatesAvailable ? 'yellow' : 'green'}
|
||||||
text={
|
text={
|
||||||
syncedTables.length === 1
|
syncedTables.length === 1
|
||||||
? `1 tracked table`
|
? `1 tracked table${
|
||||||
: `${syncedTables.length} tracked tables`
|
updatesAvailable ? ' (with pending schema updates)' : ''
|
||||||
|
}`
|
||||||
|
: `${syncedTables.length} tracked tables${
|
||||||
|
updatesAvailable ? ' (with pending schema updates)' : ''
|
||||||
|
}`
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -7,9 +7,9 @@ import { useUnsyncRemoteTable } from '@/databases/hooks/useUnsyncRemoteTable';
|
|||||||
import { SettingsListCard } from '@/settings/components/SettingsListCard';
|
import { SettingsListCard } from '@/settings/components/SettingsListCard';
|
||||||
import { SettingsIntegrationRemoteTableSyncStatusToggle } from '@/settings/integrations/components/SettingsIntegrationRemoteTableSyncStatusToggle';
|
import { SettingsIntegrationRemoteTableSyncStatusToggle } from '@/settings/integrations/components/SettingsIntegrationRemoteTableSyncStatusToggle';
|
||||||
import {
|
import {
|
||||||
|
DistantTableUpdate,
|
||||||
RemoteTable,
|
RemoteTable,
|
||||||
RemoteTableStatus,
|
RemoteTableStatus,
|
||||||
TableUpdate,
|
|
||||||
} from '~/generated-metadata/graphql';
|
} from '~/generated-metadata/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
@ -39,20 +39,22 @@ const StyledText = styled.h3`
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const getTableUpdatesText = (schemaPendingUpdates: TableUpdate[]) => {
|
const getDistantTableUpdatesText = (
|
||||||
if (schemaPendingUpdates.includes(TableUpdate.TableDeleted)) {
|
schemaPendingUpdates: DistantTableUpdate[],
|
||||||
|
) => {
|
||||||
|
if (schemaPendingUpdates.includes(DistantTableUpdate.TableDeleted)) {
|
||||||
return 'Table has been deleted';
|
return 'Table has been deleted';
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
schemaPendingUpdates.includes(TableUpdate.ColumnsAdded) &&
|
schemaPendingUpdates.includes(DistantTableUpdate.ColumnsAdded) &&
|
||||||
schemaPendingUpdates.includes(TableUpdate.ColumnsDeleted)
|
schemaPendingUpdates.includes(DistantTableUpdate.ColumnsDeleted)
|
||||||
) {
|
) {
|
||||||
return 'Columns have been added and other deleted';
|
return 'Columns have been added and other deleted';
|
||||||
}
|
}
|
||||||
if (schemaPendingUpdates.includes(TableUpdate.ColumnsAdded)) {
|
if (schemaPendingUpdates.includes(DistantTableUpdate.ColumnsAdded)) {
|
||||||
return 'Columns have been added';
|
return 'Columns have been added';
|
||||||
}
|
}
|
||||||
if (schemaPendingUpdates.includes(TableUpdate.ColumnsDeleted)) {
|
if (schemaPendingUpdates.includes(DistantTableUpdate.ColumnsDeleted)) {
|
||||||
return 'Columns have been deleted';
|
return 'Columns have been deleted';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -71,7 +73,7 @@ export const SettingsIntegrationDatabaseTablesListCard = ({
|
|||||||
...table,
|
...table,
|
||||||
id: table.name,
|
id: table.name,
|
||||||
updatesText: table.schemaPendingUpdates
|
updatesText: table.schemaPendingUpdates
|
||||||
? getTableUpdatesText(table.schemaPendingUpdates)
|
? getDistantTableUpdatesText(table.schemaPendingUpdates)
|
||||||
: null,
|
: null,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -42,7 +42,6 @@ export const useDatabaseConnection = () => {
|
|||||||
const { tables } = useGetDatabaseConnectionTables({
|
const { tables } = useGetDatabaseConnectionTables({
|
||||||
connectionId,
|
connectionId,
|
||||||
skip: !connection,
|
skip: !connection,
|
||||||
refreshData: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return { connection, integration, databaseKey, tables };
|
return { connection, integration, databaseKey, tables };
|
||||||
|
|||||||
@ -9,9 +9,9 @@ import {
|
|||||||
RemoteServerType,
|
RemoteServerType,
|
||||||
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||||
import { DistantTableColumn } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table-column';
|
|
||||||
import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table';
|
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/util/stripe-distant-tables.util';
|
import { STRIPE_DISTANT_TABLES } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/util/stripe-distant-tables.util';
|
||||||
|
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DistantTableService {
|
export class DistantTableService {
|
||||||
@ -26,7 +26,7 @@ export class DistantTableService {
|
|||||||
public getDistantTableColumns(
|
public getDistantTableColumns(
|
||||||
remoteServer: RemoteServerEntity<RemoteServerType>,
|
remoteServer: RemoteServerEntity<RemoteServerType>,
|
||||||
tableName: string,
|
tableName: string,
|
||||||
): DistantTableColumn[] {
|
): PostgresTableSchemaColumn[] {
|
||||||
if (!remoteServer.availableTables) {
|
if (!remoteServer.availableTables) {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
'Remote server available tables are not defined',
|
'Remote server available tables are not defined',
|
||||||
@ -39,13 +39,8 @@ export class DistantTableService {
|
|||||||
public async fetchDistantTables(
|
public async fetchDistantTables(
|
||||||
remoteServer: RemoteServerEntity<RemoteServerType>,
|
remoteServer: RemoteServerEntity<RemoteServerType>,
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
refreshData?: boolean,
|
|
||||||
): Promise<DistantTables> {
|
): Promise<DistantTables> {
|
||||||
if (!refreshData && remoteServer.availableTables) {
|
return this.createAvailableTables(remoteServer, workspaceId);
|
||||||
return remoteServer.availableTables;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.createAvailableTables(remoteServer, workspaceId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createAvailableTables(
|
private async createAvailableTables(
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
// Type will evolve as we add more remote table types
|
|
||||||
export type DistantTableColumn = {
|
|
||||||
columnName: string;
|
|
||||||
dataType: string;
|
|
||||||
udtName: string;
|
|
||||||
};
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { DistantTableColumn } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table-column';
|
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||||
|
|
||||||
export type DistantTables = {
|
export type DistantTables = {
|
||||||
[tableName: string]: DistantTableColumn[];
|
[tableName: string]: PostgresTableSchemaColumn[];
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
import { InputType, ID, Field } from '@nestjs/graphql';
|
import { InputType, ID } from '@nestjs/graphql';
|
||||||
|
|
||||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||||
import { IsOptional } from 'class-validator';
|
|
||||||
|
|
||||||
@InputType()
|
@InputType()
|
||||||
export class FindManyRemoteTablesInput {
|
export class FindManyRemoteTablesInput {
|
||||||
@IDField(() => ID, { description: 'The id of the remote server.' })
|
@IDField(() => ID, { description: 'The id of the remote server.' })
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
@Field(() => Boolean, {
|
|
||||||
description: 'Indicates if data from distant tables should be refreshed.',
|
|
||||||
nullable: true,
|
|
||||||
})
|
|
||||||
refreshData?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,11 +10,11 @@ export enum RemoteTableStatus {
|
|||||||
NOT_SYNCED = 'NOT_SYNCED',
|
NOT_SYNCED = 'NOT_SYNCED',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TableUpdate {
|
export enum DistantTableUpdate {
|
||||||
TABLE_DELETED = 'TABLE_DELETED',
|
TABLE_DELETED = 'TABLE_DELETED',
|
||||||
COLUMNS_DELETED = 'COLUMN_DELETED',
|
COLUMNS_DELETED = 'COLUMNS_DELETED',
|
||||||
COLUMNS_ADDED = 'COLUMN_ADDED',
|
COLUMNS_ADDED = 'COLUMNS_ADDED',
|
||||||
COLUMNS_TYPE_CHANGED = 'COLUMN_TYPE_CHANGED',
|
COLUMNS_TYPE_CHANGED = 'COLUMNS_TYPE_CHANGED',
|
||||||
}
|
}
|
||||||
|
|
||||||
registerEnumType(RemoteTableStatus, {
|
registerEnumType(RemoteTableStatus, {
|
||||||
@ -22,8 +22,8 @@ registerEnumType(RemoteTableStatus, {
|
|||||||
description: 'Status of the table',
|
description: 'Status of the table',
|
||||||
});
|
});
|
||||||
|
|
||||||
registerEnumType(TableUpdate, {
|
registerEnumType(DistantTableUpdate, {
|
||||||
name: 'TableUpdate',
|
name: 'DistantTableUpdate',
|
||||||
description: 'Schema update on a table',
|
description: 'Schema update on a table',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -43,6 +43,6 @@ export class RemoteTableDTO {
|
|||||||
schema?: string;
|
schema?: string;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@Field(() => [TableUpdate], { nullable: true })
|
@Field(() => [DistantTableUpdate], { nullable: true })
|
||||||
schemaPendingUpdates?: [TableUpdate];
|
schemaPendingUpdates?: [DistantTableUpdate];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,6 @@ export class RemoteTableResolver {
|
|||||||
return this.remoteTableService.findDistantTablesByServerId(
|
return this.remoteTableService.findDistantTablesByServerId(
|
||||||
input.id,
|
input.id,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
input.refreshData,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
||||||
import {
|
import {
|
||||||
RemoteTableStatus,
|
RemoteTableStatus,
|
||||||
TableUpdate,
|
DistantTableUpdate,
|
||||||
} from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
|
} from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
|
||||||
import {
|
import {
|
||||||
mapUdtNameToFieldType,
|
mapUdtNameToFieldType,
|
||||||
@ -38,9 +38,9 @@ import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/work
|
|||||||
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
|
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
|
||||||
import { getRemoteTableLocalName } from 'src/engine/metadata-modules/remote-server/remote-table/utils/get-remote-table-local-name.util';
|
import { getRemoteTableLocalName } from 'src/engine/metadata-modules/remote-server/remote-table/utils/get-remote-table-local-name.util';
|
||||||
import { DistantTableService } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service';
|
import { DistantTableService } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service';
|
||||||
import { DistantTableColumn } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table-column';
|
|
||||||
import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table';
|
import { DistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table';
|
||||||
import { RemoteTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/remote-table/types/remote-table-schema-column';
|
import { getForeignTableColumnName } from 'src/engine/metadata-modules/remote-server/remote-table/utils/get-foreign-table-column-name.util';
|
||||||
|
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||||
|
|
||||||
export class RemoteTableService {
|
export class RemoteTableService {
|
||||||
private readonly logger = new Logger(RemoteTableService.name);
|
private readonly logger = new Logger(RemoteTableService.name);
|
||||||
@ -62,11 +62,7 @@ export class RemoteTableService {
|
|||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async findDistantTablesByServerId(
|
public async findDistantTablesByServerId(id: string, workspaceId: string) {
|
||||||
id: string,
|
|
||||||
workspaceId: string,
|
|
||||||
refreshData?: boolean,
|
|
||||||
) {
|
|
||||||
const remoteServer = await this.remoteServerRepository.findOne({
|
const remoteServer = await this.remoteServerRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
id,
|
id,
|
||||||
@ -90,10 +86,9 @@ export class RemoteTableService {
|
|||||||
const distantTables = await this.distantTableService.fetchDistantTables(
|
const distantTables = await this.distantTableService.fetchDistantTables(
|
||||||
remoteServer,
|
remoteServer,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
refreshData,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!refreshData || currentRemoteTables.length === 0) {
|
if (currentRemoteTables.length === 0) {
|
||||||
const distantTablesWithStatus = Object.keys(distantTables).map(
|
const distantTablesWithStatus = Object.keys(distantTables).map(
|
||||||
(tableName) => ({
|
(tableName) => ({
|
||||||
name: tableName,
|
name: tableName,
|
||||||
@ -107,18 +102,41 @@ export class RemoteTableService {
|
|||||||
return distantTablesWithStatus;
|
return distantTablesWithStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.getDistantTablesWithUpdates({
|
||||||
|
remoteServerSchema: remoteServer.schema,
|
||||||
|
workspaceId,
|
||||||
|
remoteTables: currentRemoteTables,
|
||||||
|
distantTables,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getDistantTablesWithUpdates({
|
||||||
|
remoteServerSchema,
|
||||||
|
workspaceId,
|
||||||
|
remoteTables,
|
||||||
|
distantTables,
|
||||||
|
}: {
|
||||||
|
remoteServerSchema: string;
|
||||||
|
workspaceId: string;
|
||||||
|
remoteTables: RemoteTableEntity[];
|
||||||
|
distantTables: DistantTables;
|
||||||
|
}) {
|
||||||
const schemaPendingUpdates =
|
const schemaPendingUpdates =
|
||||||
await this.getSchemaUpdatesBetweenRemoteAndDistantTables({
|
await this.getSchemaUpdatesBetweenForeignAndDistantTables({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
remoteTables: currentRemoteTables,
|
remoteTables,
|
||||||
distantTables,
|
distantTables,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const remoteTablesDistantNames = remoteTables.map(
|
||||||
|
(remoteTable) => remoteTable.distantTableName,
|
||||||
|
);
|
||||||
|
|
||||||
const distantTablesWithUpdates = Object.keys(distantTables).map(
|
const distantTablesWithUpdates = Object.keys(distantTables).map(
|
||||||
(tableName) => ({
|
(tableName) => ({
|
||||||
name: tableName,
|
name: tableName,
|
||||||
schema: remoteServer.schema,
|
schema: remoteServerSchema,
|
||||||
status: currentRemoteTableDistantNames.includes(tableName)
|
status: remoteTablesDistantNames.includes(tableName)
|
||||||
? RemoteTableStatus.SYNCED
|
? RemoteTableStatus.SYNCED
|
||||||
: RemoteTableStatus.NOT_SYNCED,
|
: RemoteTableStatus.NOT_SYNCED,
|
||||||
schemaPendingUpdates: schemaPendingUpdates[tableName],
|
schemaPendingUpdates: schemaPendingUpdates[tableName],
|
||||||
@ -127,11 +145,11 @@ export class RemoteTableService {
|
|||||||
|
|
||||||
const deletedTables = Object.entries(schemaPendingUpdates)
|
const deletedTables = Object.entries(schemaPendingUpdates)
|
||||||
.filter(([_tableName, updates]) =>
|
.filter(([_tableName, updates]) =>
|
||||||
updates.includes(TableUpdate.TABLE_DELETED),
|
updates.includes(DistantTableUpdate.TABLE_DELETED),
|
||||||
)
|
)
|
||||||
.map(([tableName, updates]) => ({
|
.map(([tableName, updates]) => ({
|
||||||
name: tableName,
|
name: tableName,
|
||||||
schema: remoteServer.schema,
|
schema: remoteServerSchema,
|
||||||
status: RemoteTableStatus.SYNCED,
|
status: RemoteTableStatus.SYNCED,
|
||||||
schemaPendingUpdates: updates,
|
schemaPendingUpdates: updates,
|
||||||
}));
|
}));
|
||||||
@ -139,7 +157,7 @@ export class RemoteTableService {
|
|||||||
return distantTablesWithUpdates.concat(deletedTables);
|
return distantTablesWithUpdates.concat(deletedTables);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getSchemaUpdatesBetweenRemoteAndDistantTables({
|
private async getSchemaUpdatesBetweenForeignAndDistantTables({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
remoteTables,
|
remoteTables,
|
||||||
distantTables,
|
distantTables,
|
||||||
@ -147,7 +165,7 @@ export class RemoteTableService {
|
|||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
remoteTables: RemoteTableEntity[];
|
remoteTables: RemoteTableEntity[];
|
||||||
distantTables: DistantTables;
|
distantTables: DistantTables;
|
||||||
}): Promise<{ [tablename: string]: TableUpdate[] }> {
|
}): Promise<{ [tablename: string]: DistantTableUpdate[] }> {
|
||||||
const updates = {};
|
const updates = {};
|
||||||
|
|
||||||
for (const remoteTable of remoteTables) {
|
for (const remoteTable of remoteTables) {
|
||||||
@ -155,37 +173,39 @@ export class RemoteTableService {
|
|||||||
const tableName = remoteTable.distantTableName;
|
const tableName = remoteTable.distantTableName;
|
||||||
|
|
||||||
if (!distantTable) {
|
if (!distantTable) {
|
||||||
updates[tableName] = [TableUpdate.TABLE_DELETED];
|
updates[tableName] = [DistantTableUpdate.TABLE_DELETED];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const distantColumnNames = new Set(
|
const distantTableColumnNames = new Set(
|
||||||
distantTable.map((column) => column.columnName),
|
distantTable.map((column) =>
|
||||||
|
getForeignTableColumnName(column.columnName),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const localColumnNames = new Set(
|
const foreignTableColumnNames = new Set(
|
||||||
(
|
(
|
||||||
await this.fetchTableColumns(workspaceId, remoteTable.localTableName)
|
await this.fetchTableColumns(workspaceId, remoteTable.localTableName)
|
||||||
).map((column) => column.column_name),
|
).map((column) => column.columnName),
|
||||||
);
|
);
|
||||||
|
|
||||||
const columnsAdded = [...distantColumnNames].filter(
|
const columnsAdded = [...distantTableColumnNames].filter(
|
||||||
(columnName) => !localColumnNames.has(columnName),
|
(columnName) => !foreignTableColumnNames.has(columnName),
|
||||||
);
|
);
|
||||||
|
|
||||||
const columnsDeleted = [...localColumnNames].filter(
|
const columnsDeleted = [...foreignTableColumnNames].filter(
|
||||||
(columnName) => !distantColumnNames.has(columnName),
|
(columnName) => !distantTableColumnNames.has(columnName),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (columnsAdded.length > 0) {
|
if (columnsAdded.length > 0) {
|
||||||
updates[tableName] = [
|
updates[tableName] = [
|
||||||
...(updates[tableName] || []),
|
...(updates[tableName] || []),
|
||||||
TableUpdate.COLUMNS_ADDED,
|
DistantTableUpdate.COLUMNS_ADDED,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if (columnsDeleted.length > 0) {
|
if (columnsDeleted.length > 0) {
|
||||||
updates[tableName] = [
|
updates[tableName] = [
|
||||||
...(updates[tableName] || []),
|
...(updates[tableName] || []),
|
||||||
TableUpdate.COLUMNS_DELETED,
|
DistantTableUpdate.COLUMNS_DELETED,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -431,7 +451,7 @@ export class RemoteTableService {
|
|||||||
private async fetchTableColumns(
|
private async fetchTableColumns(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
tableName: string,
|
tableName: string,
|
||||||
): Promise<RemoteTableSchemaColumn[]> {
|
): Promise<PostgresTableSchemaColumn[]> {
|
||||||
const workspaceDataSource =
|
const workspaceDataSource =
|
||||||
await this.workspaceDataSourceService.connectToWorkspaceDataSource(
|
await this.workspaceDataSourceService.connectToWorkspaceDataSource(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -440,11 +460,17 @@ export class RemoteTableService {
|
|||||||
const schemaName =
|
const schemaName =
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
return await workspaceDataSource.query(
|
const res = await workspaceDataSource.query(
|
||||||
`SELECT column_name, data_type
|
`SELECT column_name, data_type, udt_name
|
||||||
FROM information_schema.columns
|
FROM information_schema.columns
|
||||||
WHERE table_schema = '${schemaName}' AND table_name = '${tableName}'`,
|
WHERE table_schema = '${schemaName}' AND table_name = '${tableName}'`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return res.map((column) => ({
|
||||||
|
columnName: column.column_name,
|
||||||
|
dataType: column.data_type,
|
||||||
|
udtName: column.udt_name,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createForeignTable(
|
private async createForeignTable(
|
||||||
@ -452,7 +478,7 @@ export class RemoteTableService {
|
|||||||
localTableName: string,
|
localTableName: string,
|
||||||
remoteTableInput: RemoteTableInput,
|
remoteTableInput: RemoteTableInput,
|
||||||
remoteServer: RemoteServerEntity<RemoteServerType>,
|
remoteServer: RemoteServerEntity<RemoteServerType>,
|
||||||
distantTableColumns: DistantTableColumn[],
|
distantTableColumns: PostgresTableSchemaColumn[],
|
||||||
) {
|
) {
|
||||||
const referencedTable: ReferencedTable = this.buildReferencedTable(
|
const referencedTable: ReferencedTable = this.buildReferencedTable(
|
||||||
remoteServer,
|
remoteServer,
|
||||||
@ -471,7 +497,7 @@ export class RemoteTableService {
|
|||||||
columns: distantTableColumns.map(
|
columns: distantTableColumns.map(
|
||||||
(column) =>
|
(column) =>
|
||||||
({
|
({
|
||||||
columnName: camelCase(column.columnName),
|
columnName: getForeignTableColumnName(column.columnName),
|
||||||
columnType: column.dataType,
|
columnType: column.dataType,
|
||||||
distantColumnName: column.columnName,
|
distantColumnName: column.columnName,
|
||||||
}) satisfies WorkspaceMigrationForeignColumnDefinition,
|
}) satisfies WorkspaceMigrationForeignColumnDefinition,
|
||||||
@ -500,8 +526,8 @@ export class RemoteTableService {
|
|||||||
private async createRemoteTableMetadata(
|
private async createRemoteTableMetadata(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
localTableName: string,
|
localTableName: string,
|
||||||
distantTableColumns: DistantTableColumn[],
|
distantTableColumns: PostgresTableSchemaColumn[],
|
||||||
distantTableIdColumn: DistantTableColumn,
|
distantTableIdColumn: PostgresTableSchemaColumn,
|
||||||
dataSourceMetadataId: string,
|
dataSourceMetadataId: string,
|
||||||
) {
|
) {
|
||||||
const objectMetadata = await this.objectMetadataService.createOne({
|
const objectMetadata = await this.objectMetadataService.createOne({
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
export type RemoteTableSchemaColumn = {
|
|
||||||
column_name: string;
|
|
||||||
data_type: string;
|
|
||||||
};
|
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
import camelCase from 'lodash.camelcase';
|
||||||
|
|
||||||
|
export const getForeignTableColumnName = (distantTableColumnName: string) => {
|
||||||
|
return camelCase(distantTableColumnName);
|
||||||
|
};
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
export type PostgresTableSchemaColumn = {
|
||||||
|
columnName: string;
|
||||||
|
dataType: string;
|
||||||
|
udtName: string;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user