diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index ef3678f15..e57c79ee3 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -250,6 +250,14 @@ export type DeleteOneRelationInput = { 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 = { __typename?: 'EmailPasswordResetLink'; /** Boolean that confirms query was dispatched */ @@ -330,8 +338,6 @@ export enum FileFolder { export type FindManyRemoteTablesInput = { /** The id of the remote server. */ id: Scalars['ID']['input']; - /** Indicates if data from distant tables should be refreshed. */ - refreshData?: InputMaybe; }; export type FullName = { @@ -812,7 +818,7 @@ export type RemoteTable = { id?: Maybe; name: Scalars['String']['output']; schema?: Maybe; - schemaPendingUpdates?: Maybe>; + schemaPendingUpdates?: Maybe>; status: RemoteTableStatus; }; @@ -857,14 +863,6 @@ export type Support = { supportFrontChatId?: Maybe; }; -/** Schema update on a table */ -export enum TableUpdate { - ColumnsAdded = 'COLUMNS_ADDED', - ColumnsDeleted = 'COLUMNS_DELETED', - ColumnsTypeChanged = 'COLUMNS_TYPE_CHANGED', - TableDeleted = 'TABLE_DELETED' -} - export type Telemetry = { __typename?: 'Telemetry'; 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 RemoteTableFieldsFragment = { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array | null }; +export type RemoteTableFieldsFragment = { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array | null }; export type CreateServerMutationVariables = Exact<{ 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 | null } }; +export type SyncRemoteTableMutation = { __typename?: 'Mutation', syncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array | null } }; export type UnsyncRemoteTableMutationVariables = Exact<{ input: RemoteTableInput; }>; -export type UnsyncRemoteTableMutation = { __typename?: 'Mutation', unsyncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array | null } }; +export type UnsyncRemoteTableMutation = { __typename?: 'Mutation', unsyncRemoteTable: { __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array | null } }; export type UpdateServerMutationVariables = Exact<{ 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 | null }> }; +export type GetManyRemoteTablesQuery = { __typename?: 'Query', findAvailableRemoteTablesByServerId: Array<{ __typename?: 'RemoteTable', id?: any | null, name: string, schema?: string | null, status: RemoteTableStatus, schemaPendingUpdates?: Array | null }> }; export type GetOneDatabaseConnectionQueryVariables = Exact<{ input: RemoteServerIdInput; diff --git a/packages/twenty-front/src/modules/databases/hooks/useGetDatabaseConnectionTables.ts b/packages/twenty-front/src/modules/databases/hooks/useGetDatabaseConnectionTables.ts index 064f28c72..dd50582bb 100644 --- a/packages/twenty-front/src/modules/databases/hooks/useGetDatabaseConnectionTables.ts +++ b/packages/twenty-front/src/modules/databases/hooks/useGetDatabaseConnectionTables.ts @@ -10,13 +10,11 @@ import { type UseGetDatabaseConnectionTablesParams = { connectionId: string; skip?: boolean; - refreshData?: boolean; }; export const useGetDatabaseConnectionTables = ({ connectionId, skip, - refreshData, }: UseGetDatabaseConnectionTablesParams) => { const apolloMetadataClient = useApolloMetadataClient(); @@ -29,7 +27,6 @@ export const useGetDatabaseConnectionTables = ({ variables: { input: { id: connectionId, - refreshData: refreshData, }, }, }); diff --git a/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionSyncStatus.tsx b/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionSyncStatus.tsx index b50a048a2..3ae697ccc 100644 --- a/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionSyncStatus.tsx +++ b/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseConnectionSyncStatus.tsx @@ -25,13 +25,23 @@ export const SettingsIntegrationDatabaseConnectionSyncStatus = ({ (table) => table.status === RemoteTableStatus.Synced, ); + const updatesAvailable = tables.some( + (table) => + table.schemaPendingUpdates?.length && + table.schemaPendingUpdates.length > 0, + ); + return ( ); diff --git a/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseTablesListCard.tsx b/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseTablesListCard.tsx index 465d36c3a..937d523db 100644 --- a/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseTablesListCard.tsx +++ b/packages/twenty-front/src/modules/settings/integrations/database-connection/components/SettingsIntegrationDatabaseTablesListCard.tsx @@ -7,9 +7,9 @@ import { useUnsyncRemoteTable } from '@/databases/hooks/useUnsyncRemoteTable'; import { SettingsListCard } from '@/settings/components/SettingsListCard'; import { SettingsIntegrationRemoteTableSyncStatusToggle } from '@/settings/integrations/components/SettingsIntegrationRemoteTableSyncStatusToggle'; import { + DistantTableUpdate, RemoteTable, RemoteTableStatus, - TableUpdate, } from '~/generated-metadata/graphql'; import { isDefined } from '~/utils/isDefined'; @@ -39,20 +39,22 @@ const StyledText = styled.h3` margin: 0; `; -const getTableUpdatesText = (schemaPendingUpdates: TableUpdate[]) => { - if (schemaPendingUpdates.includes(TableUpdate.TableDeleted)) { +const getDistantTableUpdatesText = ( + schemaPendingUpdates: DistantTableUpdate[], +) => { + if (schemaPendingUpdates.includes(DistantTableUpdate.TableDeleted)) { return 'Table has been deleted'; } if ( - schemaPendingUpdates.includes(TableUpdate.ColumnsAdded) && - schemaPendingUpdates.includes(TableUpdate.ColumnsDeleted) + schemaPendingUpdates.includes(DistantTableUpdate.ColumnsAdded) && + schemaPendingUpdates.includes(DistantTableUpdate.ColumnsDeleted) ) { return 'Columns have been added and other deleted'; } - if (schemaPendingUpdates.includes(TableUpdate.ColumnsAdded)) { + if (schemaPendingUpdates.includes(DistantTableUpdate.ColumnsAdded)) { return 'Columns have been added'; } - if (schemaPendingUpdates.includes(TableUpdate.ColumnsDeleted)) { + if (schemaPendingUpdates.includes(DistantTableUpdate.ColumnsDeleted)) { return 'Columns have been deleted'; } return null; @@ -71,7 +73,7 @@ export const SettingsIntegrationDatabaseTablesListCard = ({ ...table, id: table.name, updatesText: table.schemaPendingUpdates - ? getTableUpdatesText(table.schemaPendingUpdates) + ? getDistantTableUpdatesText(table.schemaPendingUpdates) : null, })), ); diff --git a/packages/twenty-front/src/modules/settings/integrations/database-connection/hooks/useDatabaseConnection.ts b/packages/twenty-front/src/modules/settings/integrations/database-connection/hooks/useDatabaseConnection.ts index 215ddf5db..1a4419577 100644 --- a/packages/twenty-front/src/modules/settings/integrations/database-connection/hooks/useDatabaseConnection.ts +++ b/packages/twenty-front/src/modules/settings/integrations/database-connection/hooks/useDatabaseConnection.ts @@ -42,7 +42,6 @@ export const useDatabaseConnection = () => { const { tables } = useGetDatabaseConnectionTables({ connectionId, skip: !connection, - refreshData: true, }); return { connection, integration, databaseKey, tables }; diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service.ts index 4d6487307..e10b1cc65 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service.ts @@ -9,9 +9,9 @@ import { RemoteServerType, } from 'src/engine/metadata-modules/remote-server/remote-server.entity'; 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 { 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() export class DistantTableService { @@ -26,7 +26,7 @@ export class DistantTableService { public getDistantTableColumns( remoteServer: RemoteServerEntity, tableName: string, - ): DistantTableColumn[] { + ): PostgresTableSchemaColumn[] { if (!remoteServer.availableTables) { throw new BadRequestException( 'Remote server available tables are not defined', @@ -39,13 +39,8 @@ export class DistantTableService { public async fetchDistantTables( remoteServer: RemoteServerEntity, workspaceId: string, - refreshData?: boolean, ): Promise { - if (!refreshData && remoteServer.availableTables) { - return remoteServer.availableTables; - } - - return await this.createAvailableTables(remoteServer, workspaceId); + return this.createAvailableTables(remoteServer, workspaceId); } private async createAvailableTables( diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table-column.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table-column.ts deleted file mode 100644 index 847a6ca2c..000000000 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table-column.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Type will evolve as we add more remote table types -export type DistantTableColumn = { - columnName: string; - dataType: string; - udtName: string; -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table.ts index 93a64b97a..aeeb52512 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/distant-table/types/distant-table.ts @@ -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 = { - [tableName: string]: DistantTableColumn[]; + [tableName: string]: PostgresTableSchemaColumn[]; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/find-many-remote-tables-input.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/find-many-remote-tables-input.ts index 515962d40..f74519cb9 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/find-many-remote-tables-input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/find-many-remote-tables-input.ts @@ -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 { IsOptional } from 'class-validator'; @InputType() export class FindManyRemoteTablesInput { @IDField(() => ID, { description: 'The id of the remote server.' }) id!: string; - - @IsOptional() - @Field(() => Boolean, { - description: 'Indicates if data from distant tables should be refreshed.', - nullable: true, - }) - refreshData?: boolean; } diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto.ts index d22ee19ee..9f93a8e8e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto.ts @@ -10,11 +10,11 @@ export enum RemoteTableStatus { NOT_SYNCED = 'NOT_SYNCED', } -export enum TableUpdate { +export enum DistantTableUpdate { TABLE_DELETED = 'TABLE_DELETED', - COLUMNS_DELETED = 'COLUMN_DELETED', - COLUMNS_ADDED = 'COLUMN_ADDED', - COLUMNS_TYPE_CHANGED = 'COLUMN_TYPE_CHANGED', + COLUMNS_DELETED = 'COLUMNS_DELETED', + COLUMNS_ADDED = 'COLUMNS_ADDED', + COLUMNS_TYPE_CHANGED = 'COLUMNS_TYPE_CHANGED', } registerEnumType(RemoteTableStatus, { @@ -22,8 +22,8 @@ registerEnumType(RemoteTableStatus, { description: 'Status of the table', }); -registerEnumType(TableUpdate, { - name: 'TableUpdate', +registerEnumType(DistantTableUpdate, { + name: 'DistantTableUpdate', description: 'Schema update on a table', }); @@ -43,6 +43,6 @@ export class RemoteTableDTO { schema?: string; @IsOptional() - @Field(() => [TableUpdate], { nullable: true }) - schemaPendingUpdates?: [TableUpdate]; + @Field(() => [DistantTableUpdate], { nullable: true }) + schemaPendingUpdates?: [DistantTableUpdate]; } diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver.ts index aa103d09b..8a7fa549a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver.ts @@ -22,7 +22,6 @@ export class RemoteTableResolver { return this.remoteTableService.findDistantTablesByServerId( input.id, workspaceId, - input.refreshData, ); } diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts index 9d3e1b6bd..af62ed712 100644 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/remote-table.service.ts @@ -10,7 +10,7 @@ import { } from 'src/engine/metadata-modules/remote-server/remote-server.entity'; import { RemoteTableStatus, - TableUpdate, + DistantTableUpdate, } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto'; import { 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 { 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 { 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 { 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 { private readonly logger = new Logger(RemoteTableService.name); @@ -62,11 +62,7 @@ export class RemoteTableService { private readonly workspaceDataSourceService: WorkspaceDataSourceService, ) {} - public async findDistantTablesByServerId( - id: string, - workspaceId: string, - refreshData?: boolean, - ) { + public async findDistantTablesByServerId(id: string, workspaceId: string) { const remoteServer = await this.remoteServerRepository.findOne({ where: { id, @@ -90,10 +86,9 @@ export class RemoteTableService { const distantTables = await this.distantTableService.fetchDistantTables( remoteServer, workspaceId, - refreshData, ); - if (!refreshData || currentRemoteTables.length === 0) { + if (currentRemoteTables.length === 0) { const distantTablesWithStatus = Object.keys(distantTables).map( (tableName) => ({ name: tableName, @@ -107,18 +102,41 @@ export class RemoteTableService { 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 = - await this.getSchemaUpdatesBetweenRemoteAndDistantTables({ + await this.getSchemaUpdatesBetweenForeignAndDistantTables({ workspaceId, - remoteTables: currentRemoteTables, + remoteTables, distantTables, }); + const remoteTablesDistantNames = remoteTables.map( + (remoteTable) => remoteTable.distantTableName, + ); + const distantTablesWithUpdates = Object.keys(distantTables).map( (tableName) => ({ name: tableName, - schema: remoteServer.schema, - status: currentRemoteTableDistantNames.includes(tableName) + schema: remoteServerSchema, + status: remoteTablesDistantNames.includes(tableName) ? RemoteTableStatus.SYNCED : RemoteTableStatus.NOT_SYNCED, schemaPendingUpdates: schemaPendingUpdates[tableName], @@ -127,11 +145,11 @@ export class RemoteTableService { const deletedTables = Object.entries(schemaPendingUpdates) .filter(([_tableName, updates]) => - updates.includes(TableUpdate.TABLE_DELETED), + updates.includes(DistantTableUpdate.TABLE_DELETED), ) .map(([tableName, updates]) => ({ name: tableName, - schema: remoteServer.schema, + schema: remoteServerSchema, status: RemoteTableStatus.SYNCED, schemaPendingUpdates: updates, })); @@ -139,7 +157,7 @@ export class RemoteTableService { return distantTablesWithUpdates.concat(deletedTables); } - private async getSchemaUpdatesBetweenRemoteAndDistantTables({ + private async getSchemaUpdatesBetweenForeignAndDistantTables({ workspaceId, remoteTables, distantTables, @@ -147,7 +165,7 @@ export class RemoteTableService { workspaceId: string; remoteTables: RemoteTableEntity[]; distantTables: DistantTables; - }): Promise<{ [tablename: string]: TableUpdate[] }> { + }): Promise<{ [tablename: string]: DistantTableUpdate[] }> { const updates = {}; for (const remoteTable of remoteTables) { @@ -155,37 +173,39 @@ export class RemoteTableService { const tableName = remoteTable.distantTableName; if (!distantTable) { - updates[tableName] = [TableUpdate.TABLE_DELETED]; + updates[tableName] = [DistantTableUpdate.TABLE_DELETED]; continue; } - const distantColumnNames = new Set( - distantTable.map((column) => column.columnName), + const distantTableColumnNames = new Set( + distantTable.map((column) => + getForeignTableColumnName(column.columnName), + ), ); - const localColumnNames = new Set( + const foreignTableColumnNames = new Set( ( await this.fetchTableColumns(workspaceId, remoteTable.localTableName) - ).map((column) => column.column_name), + ).map((column) => column.columnName), ); - const columnsAdded = [...distantColumnNames].filter( - (columnName) => !localColumnNames.has(columnName), + const columnsAdded = [...distantTableColumnNames].filter( + (columnName) => !foreignTableColumnNames.has(columnName), ); - const columnsDeleted = [...localColumnNames].filter( - (columnName) => !distantColumnNames.has(columnName), + const columnsDeleted = [...foreignTableColumnNames].filter( + (columnName) => !distantTableColumnNames.has(columnName), ); if (columnsAdded.length > 0) { updates[tableName] = [ ...(updates[tableName] || []), - TableUpdate.COLUMNS_ADDED, + DistantTableUpdate.COLUMNS_ADDED, ]; } if (columnsDeleted.length > 0) { updates[tableName] = [ ...(updates[tableName] || []), - TableUpdate.COLUMNS_DELETED, + DistantTableUpdate.COLUMNS_DELETED, ]; } } @@ -431,7 +451,7 @@ export class RemoteTableService { private async fetchTableColumns( workspaceId: string, tableName: string, - ): Promise { + ): Promise { const workspaceDataSource = await this.workspaceDataSourceService.connectToWorkspaceDataSource( workspaceId, @@ -440,11 +460,17 @@ export class RemoteTableService { const schemaName = this.workspaceDataSourceService.getSchemaName(workspaceId); - return await workspaceDataSource.query( - `SELECT column_name, data_type + const res = await workspaceDataSource.query( + `SELECT column_name, data_type, udt_name FROM information_schema.columns 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( @@ -452,7 +478,7 @@ export class RemoteTableService { localTableName: string, remoteTableInput: RemoteTableInput, remoteServer: RemoteServerEntity, - distantTableColumns: DistantTableColumn[], + distantTableColumns: PostgresTableSchemaColumn[], ) { const referencedTable: ReferencedTable = this.buildReferencedTable( remoteServer, @@ -471,7 +497,7 @@ export class RemoteTableService { columns: distantTableColumns.map( (column) => ({ - columnName: camelCase(column.columnName), + columnName: getForeignTableColumnName(column.columnName), columnType: column.dataType, distantColumnName: column.columnName, }) satisfies WorkspaceMigrationForeignColumnDefinition, @@ -500,8 +526,8 @@ export class RemoteTableService { private async createRemoteTableMetadata( workspaceId: string, localTableName: string, - distantTableColumns: DistantTableColumn[], - distantTableIdColumn: DistantTableColumn, + distantTableColumns: PostgresTableSchemaColumn[], + distantTableIdColumn: PostgresTableSchemaColumn, dataSourceMetadataId: string, ) { const objectMetadata = await this.objectMetadataService.createOne({ diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/types/remote-table-schema-column.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/types/remote-table-schema-column.ts deleted file mode 100644 index c91b7ac27..000000000 --- a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/types/remote-table-schema-column.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type RemoteTableSchemaColumn = { - column_name: string; - data_type: string; -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/utils/get-foreign-table-column-name.util.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/utils/get-foreign-table-column-name.util.ts new file mode 100644 index 000000000..e28fbe0dc --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/remote-table/utils/get-foreign-table-column-name.util.ts @@ -0,0 +1,5 @@ +import camelCase from 'lodash.camelcase'; + +export const getForeignTableColumnName = (distantTableColumnName: string) => { + return camelCase(distantTableColumnName); +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/remote-server/types/postgres-table-schema-column.ts b/packages/twenty-server/src/engine/metadata-modules/remote-server/types/postgres-table-schema-column.ts new file mode 100644 index 000000000..294abc140 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/remote-server/types/postgres-table-schema-column.ts @@ -0,0 +1,5 @@ +export type PostgresTableSchemaColumn = { + columnName: string; + dataType: string; + udtName: string; +};