mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
console (refactor): common hook to create and manage table relationships
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9264 GitOrigin-RevId: 0cdbaf4eefe0932bc72c852da3abf88be78de47c
This commit is contained in:
parent
51aca1639a
commit
530e01d458
@ -15,7 +15,10 @@ import { SuggestedRelationshipTrackModal } from '../../../DatabaseRelationships/
|
||||
import Skeleton from 'react-loading-skeleton';
|
||||
import { useAllSuggestedRelationships } from '../../../DatabaseRelationships/components/SuggestedRelationships/hooks/useAllSuggestedRelationships';
|
||||
import { useCheckRows } from '../../../DatabaseRelationships/hooks/useCheckRows';
|
||||
import { useTrackedRelationships } from './hooks/useTrackedRelationships';
|
||||
// import { useTrackedRelationships } from './hooks/useTrackedRelationships';
|
||||
import { useCreateTableRelationships } from '../../../DatabaseRelationships/hooks/useCreateTableRelationships/useCreateTableRelationships';
|
||||
import { hasuraToast } from '../../../../new-components/Toasts';
|
||||
import { DisplayToastErrorMessage } from '../../components/DisplayErrorMessage';
|
||||
|
||||
interface UntrackedRelationshipsProps {
|
||||
dataSourceName: string;
|
||||
@ -35,15 +38,18 @@ export const UntrackedRelationships: React.VFC<UntrackedRelationshipsProps> = ({
|
||||
const {
|
||||
suggestedRelationships,
|
||||
isLoadingSuggestedRelationships,
|
||||
onAddMultipleSuggestedRelationships,
|
||||
// onAddMultipleSuggestedRelationships,
|
||||
} = useAllSuggestedRelationships({
|
||||
dataSourceName,
|
||||
isEnabled: true,
|
||||
omitTracked: true,
|
||||
});
|
||||
|
||||
const { data: trackedRelationships } =
|
||||
useTrackedRelationships(dataSourceName);
|
||||
const { createTableRelationships, isLoading } =
|
||||
useCreateTableRelationships(dataSourceName);
|
||||
|
||||
// const { data: trackedRelationships } =
|
||||
// useTrackedRelationships(dataSourceName);
|
||||
|
||||
const checkboxRef = React.useRef<HTMLInputElement>(null);
|
||||
const { checkedIds, onCheck, allChecked, toggleAll, reset, inputStatus } =
|
||||
@ -54,8 +60,8 @@ export const UntrackedRelationships: React.VFC<UntrackedRelationshipsProps> = ({
|
||||
const [filteredRelationships, setFilteredRelationships] = useState<
|
||||
SuggestedRelationshipWithName[]
|
||||
>(suggestedRelationships);
|
||||
console.log('trackedRelationships', trackedRelationships);
|
||||
console.log('suggestedRelationships', suggestedRelationships);
|
||||
// console.log('trackedRelationships', trackedRelationships);
|
||||
// console.log('suggestedRelationships', suggestedRelationships);
|
||||
const serializedRelationshipNames = suggestedRelationships
|
||||
.map(rel => rel.constraintName)
|
||||
.join('-');
|
||||
@ -78,27 +84,76 @@ export const UntrackedRelationships: React.VFC<UntrackedRelationshipsProps> = ({
|
||||
checkboxRef.current.indeterminate = inputStatus === 'indeterminate';
|
||||
}, [inputStatus]);
|
||||
|
||||
const onTrackRelationship = async (
|
||||
relationship: SuggestedRelationshipWithName
|
||||
) => {
|
||||
await onAddMultipleSuggestedRelationships([relationship]);
|
||||
const onTrackRelationship = async (rel: SuggestedRelationshipWithName) => {
|
||||
await createTableRelationships({
|
||||
data: [
|
||||
{
|
||||
name: rel.constraintName,
|
||||
source: {
|
||||
fromSource: dataSourceName,
|
||||
fromTable: rel.from.table,
|
||||
},
|
||||
definition: {
|
||||
target: {
|
||||
toSource: dataSourceName,
|
||||
toTable: rel.to.table,
|
||||
},
|
||||
type: rel.type,
|
||||
detail: {
|
||||
fkConstraintOn:
|
||||
'constraint_name' in rel.from ? 'fromTable' : 'toTable',
|
||||
fromColumns: rel.from.columns,
|
||||
toColumns: rel.to.columns,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
const [isTrackingSelectedRelationships, setTrackingSelectedRelationships] =
|
||||
useState(false);
|
||||
const onTrackSelected = async () => {
|
||||
setTrackingSelectedRelationships(true);
|
||||
try {
|
||||
const selectedRelationships = suggestedRelationships.filter(rel =>
|
||||
checkedIds.includes(rel.constraintName)
|
||||
);
|
||||
const selectedRelationships = suggestedRelationships.filter(rel =>
|
||||
checkedIds.includes(rel.constraintName)
|
||||
);
|
||||
|
||||
await onAddMultipleSuggestedRelationships(selectedRelationships);
|
||||
} catch (err) {
|
||||
setTrackingSelectedRelationships(false);
|
||||
}
|
||||
reset();
|
||||
setTrackingSelectedRelationships(false);
|
||||
createTableRelationships({
|
||||
data: selectedRelationships.map(rel => ({
|
||||
name: rel.constraintName,
|
||||
source: {
|
||||
fromSource: dataSourceName,
|
||||
fromTable: rel.from.table,
|
||||
},
|
||||
definition: {
|
||||
target: {
|
||||
toSource: dataSourceName,
|
||||
toTable: rel.to.table,
|
||||
},
|
||||
type: rel.type,
|
||||
detail: {
|
||||
fkConstraintOn:
|
||||
'constraint_name' in rel.from ? 'fromTable' : 'toTable',
|
||||
fromColumns: rel.from.columns,
|
||||
toColumns: rel.to.columns,
|
||||
},
|
||||
},
|
||||
})),
|
||||
onSettled: () => {
|
||||
reset();
|
||||
},
|
||||
onSuccess: () => {
|
||||
hasuraToast({
|
||||
type: 'success',
|
||||
title: 'Successfully tracked relationships',
|
||||
});
|
||||
},
|
||||
onError: err => {
|
||||
hasuraToast({
|
||||
type: 'error',
|
||||
title: 'Error while tracking relationships',
|
||||
children: <DisplayToastErrorMessage message={err.message} />,
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
if (isLoadingSuggestedRelationships) {
|
||||
@ -125,7 +180,7 @@ export const UntrackedRelationships: React.VFC<UntrackedRelationshipsProps> = ({
|
||||
mode="primary"
|
||||
disabled={!checkedIds.length}
|
||||
onClick={onTrackSelected}
|
||||
isLoading={isTrackingSelectedRelationships}
|
||||
isLoading={isLoading}
|
||||
loadingText="Please Wait"
|
||||
>
|
||||
Track Selected ({checkedIds.length})
|
||||
|
@ -0,0 +1,49 @@
|
||||
import { UseQueryOptions, useQuery } from 'react-query';
|
||||
import { APIError } from '../../../hooks/error';
|
||||
import { DataSource, Feature } from '../../DataSource';
|
||||
import { Capabilities } from '@hasura/dc-api-types';
|
||||
import { useHttpClient } from '../../Network';
|
||||
import { useMetadata } from '../../hasura-metadata-api';
|
||||
|
||||
type AllCapabilitiesReturnType = {
|
||||
driver: string;
|
||||
capabilities: Feature | Capabilities;
|
||||
}[];
|
||||
|
||||
export const useAllDriverCapabilities = <
|
||||
FinalResult = AllCapabilitiesReturnType
|
||||
>({
|
||||
select,
|
||||
options = {},
|
||||
}: {
|
||||
select?: (data: AllCapabilitiesReturnType) => FinalResult;
|
||||
options?: UseQueryOptions<AllCapabilitiesReturnType, APIError, FinalResult>;
|
||||
}) => {
|
||||
const httpClient = useHttpClient();
|
||||
|
||||
const { data: driverNames = [], isFetching: isFetchingMetadata } =
|
||||
useMetadata(m => m.metadata.sources.map(source => source.kind));
|
||||
|
||||
return useQuery<AllCapabilitiesReturnType, APIError, FinalResult>(
|
||||
[driverNames, 'all_capabilities'],
|
||||
async () => {
|
||||
const result = driverNames.map(async driverName => {
|
||||
const capabilities =
|
||||
(await DataSource(httpClient).getDriverCapabilities(
|
||||
driverName ?? ''
|
||||
)) ?? Feature.NotImplemented;
|
||||
|
||||
return { driver: driverName, capabilities };
|
||||
});
|
||||
|
||||
const finalResult = await Promise.all(result);
|
||||
|
||||
return finalResult;
|
||||
},
|
||||
{
|
||||
enabled: !isFetchingMetadata && options.enabled,
|
||||
select,
|
||||
...options,
|
||||
}
|
||||
);
|
||||
};
|
@ -11,8 +11,7 @@ import {
|
||||
getSupportedOperators,
|
||||
} from './introspection';
|
||||
import { getTableRows } from './query';
|
||||
import { Capabilities } from '@hasura/dc-api-types';
|
||||
import { DataTypeToSQLTypeMap } from './utils';
|
||||
import { DataTypeToSQLTypeMap, bigQueryCapabilities } from './utils';
|
||||
|
||||
export type BigQueryTable = { name: string; dataset: string };
|
||||
|
||||
@ -29,9 +28,6 @@ export const bigquery: Database = {
|
||||
return Feature.NotImplemented;
|
||||
},
|
||||
getDriverCapabilities: async () => {
|
||||
const bigQueryCapabilities: Capabilities = {
|
||||
queries: {},
|
||||
};
|
||||
return Promise.resolve(bigQueryCapabilities);
|
||||
},
|
||||
getTrackableTables,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Capabilities } from '@hasura/dc-api-types';
|
||||
import { TableColumn } from '../types';
|
||||
|
||||
export const DataTypeToSQLTypeMap: Record<
|
||||
@ -18,3 +19,13 @@ export const DataTypeToSQLTypeMap: Record<
|
||||
json: [],
|
||||
float: [],
|
||||
};
|
||||
|
||||
export const bigQueryCapabilities: Capabilities = {
|
||||
queries: {
|
||||
foreach: {},
|
||||
},
|
||||
relationships: {},
|
||||
data_schema: {
|
||||
supports_foreign_keys: false,
|
||||
},
|
||||
};
|
||||
|
@ -6,7 +6,10 @@ export const postgresCapabilities: Capabilities = {
|
||||
update: {},
|
||||
delete: {},
|
||||
},
|
||||
queries: {},
|
||||
queries: {
|
||||
foreach: {},
|
||||
},
|
||||
relationships: {},
|
||||
user_defined_functions: {},
|
||||
data_schema: {
|
||||
supports_foreign_keys: true,
|
||||
|
@ -0,0 +1,110 @@
|
||||
import axios from 'axios';
|
||||
import { DataSource } from '..';
|
||||
|
||||
describe('Verify capabilities for native drivers', () => {
|
||||
it('[POSTGRES]', async () => {
|
||||
const httpClient = axios.create();
|
||||
const result = await DataSource(httpClient).getDriverCapabilities(
|
||||
'postgres'
|
||||
);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data_schema": {
|
||||
"supports_foreign_keys": true,
|
||||
},
|
||||
"mutations": {
|
||||
"delete": {},
|
||||
"insert": {},
|
||||
"update": {},
|
||||
},
|
||||
"queries": {
|
||||
"foreach": {},
|
||||
},
|
||||
"relationships": {},
|
||||
"user_defined_functions": {},
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('[COCKROACH]', async () => {
|
||||
const httpClient = axios.create();
|
||||
const result = await DataSource(httpClient).getDriverCapabilities(
|
||||
'cockroach'
|
||||
);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data_schema": {
|
||||
"supports_foreign_keys": true,
|
||||
},
|
||||
"mutations": {
|
||||
"delete": {},
|
||||
"insert": {},
|
||||
"update": {},
|
||||
},
|
||||
"queries": {
|
||||
"foreach": {},
|
||||
},
|
||||
"relationships": {},
|
||||
"user_defined_functions": {},
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('[CITUS]', async () => {
|
||||
const httpClient = axios.create();
|
||||
const result = await DataSource(httpClient).getDriverCapabilities('citus');
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data_schema": {
|
||||
"supports_foreign_keys": true,
|
||||
},
|
||||
"mutations": {
|
||||
"delete": {},
|
||||
"insert": {},
|
||||
"update": {},
|
||||
},
|
||||
"queries": {
|
||||
"foreach": {},
|
||||
},
|
||||
"relationships": {},
|
||||
"user_defined_functions": {},
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('[MSSQL]', async () => {
|
||||
const httpClient = axios.create();
|
||||
const result = await DataSource(httpClient).getDriverCapabilities('mssql');
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data_schema": {
|
||||
"supports_foreign_keys": true,
|
||||
},
|
||||
"mutations": {
|
||||
"delete": {},
|
||||
"insert": {},
|
||||
"update": {},
|
||||
},
|
||||
"queries": {
|
||||
"foreach": {},
|
||||
},
|
||||
"relationships": {},
|
||||
"user_defined_functions": {},
|
||||
}
|
||||
`);
|
||||
});
|
||||
it('[BIGQUERY]', async () => {
|
||||
const httpClient = axios.create();
|
||||
const result = await DataSource(httpClient).getDriverCapabilities(
|
||||
'bigquery'
|
||||
);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data_schema": {
|
||||
"supports_foreign_keys": false,
|
||||
},
|
||||
"queries": {
|
||||
"foreach": {},
|
||||
},
|
||||
"relationships": {},
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
@ -5,19 +5,10 @@ import {
|
||||
} from '../../../DataSource/utils';
|
||||
import { Table } from '../../../hasura-metadata-types';
|
||||
import { useCallback } from 'react';
|
||||
import { useManageLocalRelationship } from '../../hooks/useManageLocalRelationship';
|
||||
import { useManageRemoteDatabaseRelationship } from '../../hooks/useManageRemoteDatabaseRelationship';
|
||||
import { useManageRemoteSchemaRelationship } from '../../hooks/useManageRemoteSchemaRelationship';
|
||||
import {
|
||||
LocalRelationship,
|
||||
MODE,
|
||||
RemoteDatabaseRelationship,
|
||||
RemoteSchemaRelationship,
|
||||
} from '../../types';
|
||||
import { MODE } from '../../types';
|
||||
import { generateLhsFields } from './parts/MapRemoteSchemaFields/utils';
|
||||
import { Schema } from './schema';
|
||||
import { useDriverRelationshipSupport } from '../../../Data/hooks/useDriverRelationshipSupport';
|
||||
import { hasuraToast } from '../../../../new-components/Toasts';
|
||||
import { useCreateTableRelationships } from '../../hooks/useCreateTableRelationships/useCreateTableRelationships';
|
||||
|
||||
export const getTableLabel = ({
|
||||
dataSourceName,
|
||||
@ -54,141 +45,123 @@ export const useHandleSubmit = ({
|
||||
onSuccess?: () => void;
|
||||
onError?: (err: Error) => void;
|
||||
}) => {
|
||||
const { createRelationship: createLocalRelationship, isLoading } =
|
||||
useManageLocalRelationship({
|
||||
dataSourceName,
|
||||
table,
|
||||
const { createTableRelationships, ...rest } = useCreateTableRelationships(
|
||||
dataSourceName,
|
||||
{
|
||||
onSuccess,
|
||||
onError,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
const {
|
||||
createRelationship: createRemoteDatabaseRelationship,
|
||||
editRelationship: editRemoteDatabaseRelationship,
|
||||
isLoading: remoteDatabaseRelationshipLoading,
|
||||
} = useManageRemoteDatabaseRelationship({
|
||||
dataSourceName,
|
||||
onSuccess,
|
||||
onError,
|
||||
});
|
||||
|
||||
const {
|
||||
createRelationship: createRemoteSchemaRelationship,
|
||||
editRelationship: editRemoteSchemaRelationship,
|
||||
isLoading: remoteSchemaRelationshipLoading,
|
||||
} = useManageRemoteSchemaRelationship({
|
||||
dataSourceName,
|
||||
onSuccess,
|
||||
onError,
|
||||
});
|
||||
|
||||
const { driverSupportsLocalRelationship, driverSupportsRemoteRelationship } =
|
||||
useDriverRelationshipSupport({
|
||||
dataSourceName,
|
||||
});
|
||||
const handleSubmit = useCallback(
|
||||
(formData: Schema) => {
|
||||
const { fromSource, toSource, details } = formData;
|
||||
|
||||
if (
|
||||
!driverSupportsLocalRelationship &&
|
||||
!driverSupportsRemoteRelationship
|
||||
) {
|
||||
hasuraToast({
|
||||
type: 'error',
|
||||
title: 'Not able to track',
|
||||
message: `This datasource does not support tracking of relationships.`,
|
||||
if (toSource.type === 'remoteSchema' && 'rsFieldMapping' in details) {
|
||||
createTableRelationships({
|
||||
data: [
|
||||
{
|
||||
name: formData.name,
|
||||
source: {
|
||||
fromSource: fromSource.dataSourceName,
|
||||
fromTable: fromSource.table,
|
||||
},
|
||||
isEditMode: mode === MODE.EDIT,
|
||||
definition: {
|
||||
target: {
|
||||
toRemoteSchema: toSource.remoteSchema,
|
||||
},
|
||||
detail: {
|
||||
lhs_fields: generateLhsFields(details.rsFieldMapping),
|
||||
remote_field: details.rsFieldMapping,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// remote database relationship
|
||||
/**
|
||||
* Same database relationship
|
||||
*/
|
||||
if (
|
||||
driverSupportsRemoteRelationship &&
|
||||
toSource.type === 'table' &&
|
||||
(!driverSupportsLocalRelationship || // if local relationship is not supported, we can create a remote relationship
|
||||
toSource.dataSourceName !== dataSourceName) && // if local relationship is supported, we can create a remote relationship only if the table is from a different data source
|
||||
fromSource.dataSourceName === toSource.dataSourceName &&
|
||||
'columnMap' in details
|
||||
) {
|
||||
const remoteDatabaseRelationship: RemoteDatabaseRelationship = {
|
||||
name: formData.name,
|
||||
type: 'remoteDatabaseRelationship',
|
||||
fromSource: fromSource.dataSourceName,
|
||||
fromTable: fromSource.table,
|
||||
relationshipType: details.relationshipType,
|
||||
definition: {
|
||||
toSource: toSource.dataSourceName,
|
||||
toTable: toSource.table,
|
||||
mapping: (details.columnMap ?? []).reduce(
|
||||
(acc, entry) => ({ ...acc, [entry.from]: entry.to }),
|
||||
{}
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
if (mode === MODE.CREATE)
|
||||
createRemoteDatabaseRelationship(remoteDatabaseRelationship);
|
||||
else editRemoteDatabaseRelationship(remoteDatabaseRelationship);
|
||||
} else if (
|
||||
toSource.type === 'table' &&
|
||||
toSource.dataSourceName === dataSourceName &&
|
||||
'columnMap' in details &&
|
||||
driverSupportsLocalRelationship
|
||||
) {
|
||||
const localRelationship: LocalRelationship = {
|
||||
name: formData.name,
|
||||
type: 'localRelationship',
|
||||
fromSource: fromSource.dataSourceName,
|
||||
fromTable: fromSource.table,
|
||||
relationshipType: details.relationshipType,
|
||||
definition: {
|
||||
toTable: toSource.table,
|
||||
mapping: (details.columnMap ?? []).reduce(
|
||||
(acc, entry) => ({ ...acc, [entry.from]: entry.to }),
|
||||
{}
|
||||
),
|
||||
},
|
||||
};
|
||||
createLocalRelationship(localRelationship);
|
||||
console.log('here', formData);
|
||||
createTableRelationships({
|
||||
data: [
|
||||
{
|
||||
name: formData.name,
|
||||
source: {
|
||||
fromSource: fromSource.dataSourceName,
|
||||
fromTable: fromSource.table,
|
||||
},
|
||||
isEditMode: mode === MODE.EDIT,
|
||||
definition: {
|
||||
target: {
|
||||
toSource: toSource.dataSourceName,
|
||||
toTable: toSource.table,
|
||||
},
|
||||
type:
|
||||
details.relationshipType === 'Object' ? 'object' : 'array',
|
||||
detail: {
|
||||
columnMapping: (details.columnMap ?? []).reduce(
|
||||
(acc, entry) => ({ ...acc, [entry.from]: entry.to }),
|
||||
{}
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// remote schema relationship
|
||||
if (toSource.type === 'remoteSchema' && 'rsFieldMapping' in details) {
|
||||
const remoteSchemaRelationship: RemoteSchemaRelationship = {
|
||||
name: formData.name,
|
||||
type: 'remoteSchemaRelationship',
|
||||
relationshipType: 'Remote',
|
||||
fromSource: fromSource.dataSourceName,
|
||||
fromTable: fromSource.table,
|
||||
definition: {
|
||||
toRemoteSchema: toSource.remoteSchema,
|
||||
lhs_fields: generateLhsFields(details.rsFieldMapping),
|
||||
remote_field: details.rsFieldMapping,
|
||||
},
|
||||
};
|
||||
if (mode === MODE.CREATE)
|
||||
createRemoteSchemaRelationship(remoteSchemaRelationship);
|
||||
else editRemoteSchemaRelationship(remoteSchemaRelationship);
|
||||
/**
|
||||
* remote database relationship
|
||||
*/
|
||||
if (
|
||||
toSource.type === 'table' &&
|
||||
fromSource.dataSourceName !== toSource.dataSourceName &&
|
||||
'columnMap' in details
|
||||
) {
|
||||
createTableRelationships({
|
||||
data: [
|
||||
{
|
||||
name: formData.name,
|
||||
source: {
|
||||
fromSource: fromSource.dataSourceName,
|
||||
fromTable: fromSource.table,
|
||||
},
|
||||
isEditMode: mode === MODE.EDIT,
|
||||
definition: {
|
||||
target: {
|
||||
toRemoteSource: toSource.dataSourceName,
|
||||
toRemoteTable: toSource.table,
|
||||
},
|
||||
type:
|
||||
details.relationshipType === 'Object' ? 'object' : 'array',
|
||||
detail: {
|
||||
columnMapping: (details.columnMap ?? []).reduce(
|
||||
(acc, entry) => ({ ...acc, [entry.from]: entry.to }),
|
||||
{}
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
return;
|
||||
}
|
||||
},
|
||||
[
|
||||
createLocalRelationship,
|
||||
createRemoteDatabaseRelationship,
|
||||
createRemoteSchemaRelationship,
|
||||
dataSourceName,
|
||||
editRemoteDatabaseRelationship,
|
||||
editRemoteSchemaRelationship,
|
||||
mode,
|
||||
driverSupportsLocalRelationship,
|
||||
driverSupportsRemoteRelationship,
|
||||
]
|
||||
[createTableRelationships, mode]
|
||||
);
|
||||
|
||||
return {
|
||||
handleSubmit,
|
||||
isLoading:
|
||||
isLoading ||
|
||||
remoteDatabaseRelationshipLoading ||
|
||||
remoteSchemaRelationshipLoading,
|
||||
...rest,
|
||||
};
|
||||
};
|
||||
|
@ -10,6 +10,8 @@ import {
|
||||
SuggestedRelationshipWithName,
|
||||
useSuggestedRelationships,
|
||||
} from '../SuggestedRelationships/hooks/useSuggestedRelationships';
|
||||
import { useCreateTableRelationships } from '../../hooks/useCreateTableRelationships/useCreateTableRelationships';
|
||||
import { DisplayToastErrorMessage } from '../../../Data/components/DisplayErrorMessage';
|
||||
|
||||
type SuggestedRelationshipTrackModalProps = {
|
||||
relationship: SuggestedRelationshipWithName;
|
||||
@ -20,33 +22,58 @@ type SuggestedRelationshipTrackModalProps = {
|
||||
export const SuggestedRelationshipTrackModal: React.VFC<
|
||||
SuggestedRelationshipTrackModalProps
|
||||
> = ({ relationship, dataSourceName, onClose }) => {
|
||||
const {
|
||||
onAddSuggestedRelationship,
|
||||
isAddingSuggestedRelationship,
|
||||
refetchSuggestedRelationships,
|
||||
} = useSuggestedRelationships({
|
||||
const { refetchSuggestedRelationships } = useSuggestedRelationships({
|
||||
dataSourceName,
|
||||
table: relationship.from.table,
|
||||
existingRelationships: [],
|
||||
isEnabled: true,
|
||||
});
|
||||
|
||||
const onTrackRelationship = async (relationshipName: string) => {
|
||||
try {
|
||||
await onAddSuggestedRelationship({
|
||||
...relationship,
|
||||
constraintName: relationshipName,
|
||||
});
|
||||
const { createTableRelationships, isLoading } =
|
||||
useCreateTableRelationships(dataSourceName);
|
||||
|
||||
refetchSuggestedRelationships();
|
||||
onClose();
|
||||
} catch (err: unknown) {
|
||||
hasuraToast({
|
||||
title: 'Error',
|
||||
message: err instanceof Error ? err.message : 'An error occurred',
|
||||
type: 'error',
|
||||
});
|
||||
}
|
||||
const onTrackRelationship = async (relationshipName: string) => {
|
||||
createTableRelationships({
|
||||
data: [
|
||||
{
|
||||
name: relationshipName,
|
||||
source: {
|
||||
fromSource: dataSourceName,
|
||||
fromTable: relationship.from.table,
|
||||
},
|
||||
definition: {
|
||||
target: {
|
||||
toSource: dataSourceName,
|
||||
toTable: relationship.to.table,
|
||||
},
|
||||
type: relationship.type,
|
||||
detail: {
|
||||
fkConstraintOn:
|
||||
'constraint_name' in relationship.from
|
||||
? 'fromTable'
|
||||
: 'toTable',
|
||||
fromColumns: relationship.from.columns,
|
||||
toColumns: relationship.to.columns,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
onSuccess: () => {
|
||||
hasuraToast({
|
||||
type: 'success',
|
||||
title: 'Tracked Successfully',
|
||||
});
|
||||
refetchSuggestedRelationships();
|
||||
onClose();
|
||||
},
|
||||
onError: err => {
|
||||
hasuraToast({
|
||||
type: 'error',
|
||||
title: 'Failed to track',
|
||||
children: <DisplayToastErrorMessage message={err.message} />,
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const { Form, methods } = useConsoleForm({
|
||||
@ -85,7 +112,7 @@ export const SuggestedRelationshipTrackModal: React.VFC<
|
||||
callToDeny="Cancel"
|
||||
callToAction="Track relationship"
|
||||
onClose={onClose}
|
||||
isLoading={isAddingSuggestedRelationship}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</>
|
||||
</Form>
|
||||
|
@ -0,0 +1,24 @@
|
||||
import {
|
||||
AllowedRelationshipDefinitions,
|
||||
LocalTableRelationshipDefinition,
|
||||
RemoteSchemaRelationshipDefinition,
|
||||
RemoteTableRelationshipDefinition,
|
||||
} from './types';
|
||||
|
||||
export const isLocalTableRelationshipDefinition = (
|
||||
value: AllowedRelationshipDefinitions
|
||||
): value is LocalTableRelationshipDefinition => {
|
||||
return 'toSource' in value.target;
|
||||
};
|
||||
|
||||
export const isRemoteTableRelationshipDefinition = (
|
||||
value: AllowedRelationshipDefinitions
|
||||
): value is RemoteTableRelationshipDefinition => {
|
||||
return 'toRemoteSource' in value.target;
|
||||
};
|
||||
|
||||
export const isRemoteSchemaRelationshipDefinition = (
|
||||
value: AllowedRelationshipDefinitions
|
||||
): value is RemoteSchemaRelationshipDefinition => {
|
||||
return 'toRemoteSchema' in value.target;
|
||||
};
|
@ -0,0 +1,74 @@
|
||||
import { Table } from '../../../hasura-metadata-types';
|
||||
export type TableRelationshipBasicDetails = {
|
||||
driver: string;
|
||||
name: string;
|
||||
source: { fromSource: string; fromTable: Table };
|
||||
isEditMode?: boolean;
|
||||
};
|
||||
|
||||
export type LocalTableRelationshipDefinition = {
|
||||
target: {
|
||||
toSource: string;
|
||||
toTable: Table;
|
||||
};
|
||||
type: 'array' | 'object';
|
||||
detail:
|
||||
| {
|
||||
fkConstraintOn: 'fromTable' | 'toTable';
|
||||
fromColumns: string[];
|
||||
toColumns: string[];
|
||||
}
|
||||
| { columnMapping: Record<string, string> };
|
||||
};
|
||||
|
||||
export type RemoteSchemaRelationshipDefinition = {
|
||||
target: {
|
||||
toRemoteSchema: string;
|
||||
};
|
||||
detail: { lhs_fields: string[]; remote_field: Record<string, any> };
|
||||
};
|
||||
|
||||
export type RemoteTableRelationshipDefinition = {
|
||||
target: {
|
||||
toRemoteSource: string;
|
||||
toRemoteTable: Table;
|
||||
};
|
||||
type: 'array' | 'object';
|
||||
detail: { columnMapping: Record<string, string> };
|
||||
};
|
||||
|
||||
export type AllowedRelationshipDefinitions =
|
||||
| LocalTableRelationshipDefinition
|
||||
| RemoteSchemaRelationshipDefinition
|
||||
| RemoteTableRelationshipDefinition;
|
||||
|
||||
export type CreateTableRelationshipRequestBodyProps =
|
||||
TableRelationshipBasicDetails & {
|
||||
definition: AllowedRelationshipDefinitions;
|
||||
targetCapabilities: {
|
||||
isLocalTableRelationshipSupported: boolean;
|
||||
isRemoteTableRelationshipSupported: boolean;
|
||||
isRemoteSchemaRelationshipSupported: boolean;
|
||||
};
|
||||
sourceCapabilities: {
|
||||
isLocalTableRelationshipSupported: boolean;
|
||||
isRemoteTableRelationshipSupported: boolean;
|
||||
isRemoteSchemaRelationshipSupported: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type RenameRelationshipProps = {
|
||||
name: string;
|
||||
driver: string;
|
||||
new_name: string;
|
||||
source: string;
|
||||
table: Table;
|
||||
};
|
||||
|
||||
export type DeleteRelationshipProps = {
|
||||
driver: string;
|
||||
name: string;
|
||||
table: Table;
|
||||
source: string;
|
||||
isRemote: boolean;
|
||||
};
|
@ -0,0 +1,267 @@
|
||||
import { useCallback } from 'react';
|
||||
import { isObject } from '../../../../components/Common/utils/jsUtils';
|
||||
import { transformErrorResponse } from '../../../Data/errorUtils';
|
||||
// import {
|
||||
// useAllDriverCapabilities,
|
||||
// useDriverCapabilities,
|
||||
// } from '../../../Data/hooks/useDriverCapabilities';
|
||||
import { Feature } from '../../../DataSource';
|
||||
import { useMetadataMigration } from '../../../MetadataAPI';
|
||||
import { MetadataMigrationOptions } from '../../../MetadataAPI/hooks/useMetadataMigration';
|
||||
import {
|
||||
areTablesEqual,
|
||||
useInvalidateMetadata,
|
||||
useMetadata,
|
||||
} from '../../../hasura-metadata-api';
|
||||
import {
|
||||
createTableRelationshipRequestBody,
|
||||
deleteTableRelationshipRequestBody,
|
||||
renameRelationshipRequestBody,
|
||||
} from './utils';
|
||||
import {
|
||||
DeleteRelationshipProps,
|
||||
LocalTableRelationshipDefinition,
|
||||
RemoteSchemaRelationshipDefinition,
|
||||
RemoteTableRelationshipDefinition,
|
||||
RenameRelationshipProps,
|
||||
TableRelationshipBasicDetails,
|
||||
} from './types';
|
||||
import { Table } from '../../../hasura-metadata-types';
|
||||
import { useAllDriverCapabilities } from '../../../Data/hooks/useAllDriverCapabilities';
|
||||
|
||||
type AllowedRelationshipDefinitions =
|
||||
| Omit<LocalTableRelationshipDefinition, 'capabilities'>
|
||||
| Omit<RemoteTableRelationshipDefinition, 'capabilities'>
|
||||
| Omit<RemoteSchemaRelationshipDefinition, 'capabilities'>;
|
||||
|
||||
type CreateTableRelationshipProps = Omit<
|
||||
TableRelationshipBasicDetails,
|
||||
'driver'
|
||||
> & {
|
||||
definition: AllowedRelationshipDefinitions;
|
||||
};
|
||||
|
||||
type RenameTableRelationshipProps = Omit<RenameRelationshipProps, 'driver'>;
|
||||
|
||||
type DeleteTableRelationshipProps = Omit<
|
||||
DeleteRelationshipProps,
|
||||
'driver' | 'isRemote'
|
||||
>;
|
||||
|
||||
const defaultCapabilities = {
|
||||
isLocalTableRelationshipSupported: false,
|
||||
isRemoteTableRelationshipSupported: false,
|
||||
isRemoteSchemaRelationshipSupported: true,
|
||||
};
|
||||
|
||||
const getTargetName = (target: AllowedRelationshipDefinitions['target']) => {
|
||||
if ('toRemoteSchema' in target) return null;
|
||||
|
||||
if ('toRemoteSource' in target) return target.toRemoteSource;
|
||||
|
||||
return target.toSource;
|
||||
};
|
||||
|
||||
export const useCreateTableRelationships = (
|
||||
dataSourceName: string,
|
||||
globalMutateOptions?: MetadataMigrationOptions
|
||||
) => {
|
||||
const invalidateMetadata = useInvalidateMetadata();
|
||||
|
||||
// get these capabilities
|
||||
|
||||
const { data: driverCapabilties = [] } = useAllDriverCapabilities({
|
||||
select: data => {
|
||||
const result = data.map(item => {
|
||||
if (item.capabilities === Feature.NotImplemented)
|
||||
return {
|
||||
driver: item.driver,
|
||||
capabilities: {
|
||||
isLocalTableRelationshipSupported: false,
|
||||
isRemoteTableRelationshipSupported: false,
|
||||
isRemoteSchemaRelationshipSupported: false,
|
||||
},
|
||||
};
|
||||
return {
|
||||
driver: item.driver,
|
||||
capabilities: {
|
||||
isLocalTableRelationshipSupported: isObject(
|
||||
item.capabilities.relationships
|
||||
),
|
||||
isRemoteTableRelationshipSupported: isObject(
|
||||
item.capabilities.queries?.foreach
|
||||
),
|
||||
isRemoteSchemaRelationshipSupported: true,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
});
|
||||
|
||||
// const {
|
||||
// data: capabilities = {
|
||||
// isLocalTableRelationshipSupported: false,
|
||||
// isRemoteTableRelationshipSupported: false,
|
||||
// isRemoteSchemaRelationshipSupported: true,
|
||||
// },
|
||||
// } = useDriverCapabilities({
|
||||
// dataSourceName,
|
||||
// select: data => {
|
||||
// if (data === Feature.NotImplemented)
|
||||
// return {
|
||||
// isLocalTableRelationshipSupported: false,
|
||||
// isRemoteTableRelationshipSupported: false,
|
||||
// isRemoteSchemaRelationshipSupported: false,
|
||||
// };
|
||||
|
||||
// return {
|
||||
// isLocalTableRelationshipSupported: isObject(data.relationships),
|
||||
// isRemoteTableRelationshipSupported: isObject(data.queries?.foreach),
|
||||
// isRemoteSchemaRelationshipSupported: true,
|
||||
// };
|
||||
// },
|
||||
// });
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
||||
const { data: { metadataSources = [], resource_version } = {} } = useMetadata(
|
||||
m => ({
|
||||
metadataSources: m.metadata.sources,
|
||||
resource_version: m.resource_version,
|
||||
})
|
||||
);
|
||||
|
||||
const getDriver = useCallback(
|
||||
(source: string) => metadataSources.find(s => s.name === source)?.kind,
|
||||
[metadataSources]
|
||||
);
|
||||
|
||||
const isRemoteRelationship = useCallback(
|
||||
(source: string, table: Table, relName: string) => {
|
||||
return !!metadataSources
|
||||
.find(s => s.name === source)
|
||||
?.tables.find(t => areTablesEqual(t.table, table))
|
||||
?.remote_relationships?.find(r => r.name === relName);
|
||||
},
|
||||
[metadataSources]
|
||||
);
|
||||
|
||||
const { mutate, ...rest } = useMetadataMigration({
|
||||
...globalMutateOptions,
|
||||
errorTransform: transformErrorResponse,
|
||||
onSuccess: (data, variable, ctx) => {
|
||||
invalidateMetadata();
|
||||
globalMutateOptions?.onSuccess?.(data, variable, ctx);
|
||||
},
|
||||
});
|
||||
|
||||
const createTableRelationships = useCallback(
|
||||
async ({
|
||||
data,
|
||||
...options
|
||||
}: { data: CreateTableRelationshipProps[] } & MetadataMigrationOptions) => {
|
||||
const payloads = data.map(item => {
|
||||
return createTableRelationshipRequestBody({
|
||||
driver: getDriver(item.source.fromSource) ?? '',
|
||||
name: item.name,
|
||||
source: {
|
||||
fromSource: item.source.fromSource,
|
||||
fromTable: item.source.fromTable,
|
||||
},
|
||||
definition: {
|
||||
...item.definition,
|
||||
},
|
||||
sourceCapabilities:
|
||||
driverCapabilties.find(
|
||||
c => c.driver === getDriver(item.source.fromSource)
|
||||
)?.capabilities ?? defaultCapabilities,
|
||||
targetCapabilities:
|
||||
driverCapabilties.find(
|
||||
c =>
|
||||
c.driver ===
|
||||
getDriver(getTargetName(item.definition.target) ?? '')
|
||||
)?.capabilities ?? defaultCapabilities,
|
||||
});
|
||||
});
|
||||
|
||||
mutate(
|
||||
{
|
||||
query: {
|
||||
type: 'bulk_keep_going',
|
||||
args: payloads,
|
||||
resource_version,
|
||||
},
|
||||
},
|
||||
options
|
||||
);
|
||||
},
|
||||
[driverCapabilties, getDriver, mutate, resource_version]
|
||||
);
|
||||
|
||||
const renameRelationships = useCallback(
|
||||
async ({
|
||||
data,
|
||||
...options
|
||||
}: { data: RenameTableRelationshipProps[] } & MetadataMigrationOptions) => {
|
||||
const payloads = data.map(item => {
|
||||
return renameRelationshipRequestBody({
|
||||
driver: getDriver(item.source) ?? '',
|
||||
name: item.name,
|
||||
source: item.source,
|
||||
new_name: item.new_name,
|
||||
table: item.table,
|
||||
});
|
||||
});
|
||||
|
||||
mutate(
|
||||
{
|
||||
query: {
|
||||
type: 'bulk_keep_going',
|
||||
args: payloads,
|
||||
resource_version,
|
||||
},
|
||||
},
|
||||
options
|
||||
);
|
||||
},
|
||||
[getDriver, mutate, resource_version]
|
||||
);
|
||||
|
||||
const deleteRelationships = useCallback(
|
||||
async ({
|
||||
data,
|
||||
...options
|
||||
}: { data: DeleteTableRelationshipProps[] } & MetadataMigrationOptions) => {
|
||||
const payloads = data.map(item => {
|
||||
return deleteTableRelationshipRequestBody({
|
||||
driver: getDriver(item.source) ?? '',
|
||||
name: item.name,
|
||||
source: item.source,
|
||||
table: item.table,
|
||||
isRemote: isRemoteRelationship(item.source, item.table, item.name),
|
||||
});
|
||||
});
|
||||
|
||||
mutate(
|
||||
{
|
||||
query: {
|
||||
type: 'bulk_keep_going',
|
||||
args: payloads,
|
||||
resource_version,
|
||||
},
|
||||
},
|
||||
options
|
||||
);
|
||||
},
|
||||
[getDriver, isRemoteRelationship, mutate, resource_version]
|
||||
);
|
||||
|
||||
return {
|
||||
createTableRelationships,
|
||||
renameRelationships,
|
||||
deleteRelationships,
|
||||
...rest,
|
||||
};
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,280 @@
|
||||
import { Table } from '../../../hasura-metadata-types';
|
||||
import zipObject from 'lodash/zipObject';
|
||||
import {
|
||||
CreateTableRelationshipRequestBodyProps,
|
||||
DeleteRelationshipProps,
|
||||
RenameRelationshipProps,
|
||||
} from './types';
|
||||
import {
|
||||
isLocalTableRelationshipDefinition,
|
||||
isRemoteSchemaRelationshipDefinition,
|
||||
isRemoteTableRelationshipDefinition,
|
||||
} from './typeGuards';
|
||||
|
||||
const createLocalFkRelationshipRequestBody = (props: {
|
||||
name: string;
|
||||
type: 'array' | 'object';
|
||||
driver: string;
|
||||
source: string;
|
||||
fromTable: Table;
|
||||
toTable: Table;
|
||||
fkConstraintOn: 'fromTable' | 'toTable';
|
||||
fromColumns: string[];
|
||||
toColumns: string[];
|
||||
}) => {
|
||||
return {
|
||||
type: `${props.driver}_create_${props.type}_relationship`,
|
||||
args: {
|
||||
table: props.fromTable,
|
||||
name: props.name,
|
||||
source: props.source,
|
||||
using: {
|
||||
foreign_key_constraint_on:
|
||||
props.fkConstraintOn === 'fromTable'
|
||||
? props.fromColumns
|
||||
: {
|
||||
table: props.toTable,
|
||||
columns: props.toColumns,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const renameRelationshipRequestBody = (
|
||||
props: RenameRelationshipProps
|
||||
) => ({
|
||||
type: `${props.driver}_rename_relationship`,
|
||||
args: {
|
||||
table: props.table,
|
||||
name: props.name,
|
||||
source: props.source,
|
||||
new_name: props.new_name,
|
||||
},
|
||||
});
|
||||
|
||||
const createLocalManualRelationship = (props: {
|
||||
name: string;
|
||||
type: 'array' | 'object';
|
||||
driver: string;
|
||||
source: string;
|
||||
fromTable: Table;
|
||||
toTable: Table;
|
||||
columnMapping: Record<string, string>;
|
||||
}) => {
|
||||
return {
|
||||
type: `${props.driver}_create_${props.type}_relationship`,
|
||||
args: {
|
||||
table: props.fromTable,
|
||||
name: props.name,
|
||||
source: props.source,
|
||||
using: {
|
||||
manual_configuration: {
|
||||
remote_table: props.toTable,
|
||||
column_mapping: props.columnMapping,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const createRemoteTableRelationshipRequestBody = (props: {
|
||||
name: string;
|
||||
type: 'array' | 'object';
|
||||
driver: string;
|
||||
fromSource: string;
|
||||
toSource: string;
|
||||
fromTable: Table;
|
||||
toTable: Table;
|
||||
columnMapping: Record<string, string>;
|
||||
editMode?: boolean;
|
||||
}) => {
|
||||
return {
|
||||
type: `${props.driver}_${
|
||||
props.editMode ? 'update' : 'create'
|
||||
}_remote_relationship`,
|
||||
args: {
|
||||
name: props.name,
|
||||
source: props.fromSource,
|
||||
table: props.fromTable,
|
||||
definition: {
|
||||
to_source: {
|
||||
relationship_type: props.type,
|
||||
source: props.toSource,
|
||||
table: props.toTable,
|
||||
field_mapping: props.columnMapping,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const createRemoteSchemaRelationshipRequestBody = (props: {
|
||||
name: string;
|
||||
driver: string;
|
||||
fromSource: string;
|
||||
fromTable: Table;
|
||||
toRemoteSchema: string;
|
||||
lhs_fields: string[];
|
||||
remote_field: Record<string, any>;
|
||||
editMode?: boolean;
|
||||
}) => {
|
||||
return {
|
||||
type: `${props.driver}_${
|
||||
props.editMode ? 'update' : 'create'
|
||||
}_remote_relationship`,
|
||||
args: {
|
||||
name: props.name,
|
||||
source: props.fromSource,
|
||||
table: props.fromTable,
|
||||
definition: {
|
||||
to_remote_schema: {
|
||||
remote_schema: props.toRemoteSchema,
|
||||
lhs_fields: props.lhs_fields,
|
||||
remote_field: props.remote_field,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const createTableRelationshipRequestBody = (
|
||||
props: CreateTableRelationshipRequestBodyProps
|
||||
) => {
|
||||
if (isLocalTableRelationshipDefinition(props.definition)) {
|
||||
if (props.isEditMode) {
|
||||
if (
|
||||
!props.sourceCapabilities.isLocalTableRelationshipSupported &&
|
||||
props.targetCapabilities.isRemoteTableRelationshipSupported
|
||||
) {
|
||||
return createRemoteTableRelationshipRequestBody({
|
||||
name: props.name,
|
||||
driver: props.driver,
|
||||
type: props.definition.type,
|
||||
fromSource: props.source.fromSource,
|
||||
toSource: props.definition.target.toSource,
|
||||
fromTable: props.source.fromTable,
|
||||
toTable: props.definition.target.toTable,
|
||||
columnMapping:
|
||||
'fkConstraintOn' in props.definition.detail
|
||||
? zipObject(
|
||||
props.definition.detail.fromColumns,
|
||||
props.definition.detail.toColumns
|
||||
)
|
||||
: props.definition.detail.columnMapping,
|
||||
editMode: true,
|
||||
});
|
||||
}
|
||||
throw Error('Edit Local Relationship not supported');
|
||||
}
|
||||
|
||||
if (props.source.fromSource === props.definition.target.toSource) {
|
||||
if (props.sourceCapabilities.isLocalTableRelationshipSupported) {
|
||||
return 'fkConstraintOn' in props.definition.detail
|
||||
? createLocalFkRelationshipRequestBody({
|
||||
name: props.name,
|
||||
driver: props.driver,
|
||||
source: props.source.fromSource,
|
||||
type: props.definition.type,
|
||||
fromTable: props.source.fromTable,
|
||||
toTable: props.definition.target.toTable,
|
||||
fkConstraintOn: props.definition.detail.fkConstraintOn,
|
||||
fromColumns: props.definition.detail.fromColumns,
|
||||
toColumns: props.definition.detail.toColumns,
|
||||
})
|
||||
: createLocalManualRelationship({
|
||||
name: props.name,
|
||||
driver: props.driver,
|
||||
source: props.source.fromSource,
|
||||
type: props.definition.type,
|
||||
fromTable: props.source.fromTable,
|
||||
toTable: props.definition.target.toTable,
|
||||
columnMapping: props.definition.detail.columnMapping,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
!props.sourceCapabilities.isLocalTableRelationshipSupported &&
|
||||
props.targetCapabilities.isRemoteTableRelationshipSupported
|
||||
) {
|
||||
return createRemoteTableRelationshipRequestBody({
|
||||
name: props.name,
|
||||
driver: props.driver,
|
||||
type: props.definition.type,
|
||||
fromSource: props.source.fromSource,
|
||||
toSource: props.definition.target.toSource,
|
||||
fromTable: props.source.fromTable,
|
||||
toTable: props.definition.target.toTable,
|
||||
columnMapping:
|
||||
'fkConstraintOn' in props.definition.detail
|
||||
? zipObject(
|
||||
props.definition.detail.fromColumns,
|
||||
props.definition.detail.toColumns
|
||||
)
|
||||
: props.definition.detail.columnMapping,
|
||||
});
|
||||
}
|
||||
|
||||
throw Error('Local Relationship not supported');
|
||||
}
|
||||
}
|
||||
|
||||
if (isRemoteTableRelationshipDefinition(props.definition)) {
|
||||
if (props.targetCapabilities.isRemoteTableRelationshipSupported) {
|
||||
return createRemoteTableRelationshipRequestBody({
|
||||
name: props.name,
|
||||
driver: props.driver,
|
||||
type: props.definition.type,
|
||||
fromSource: props.source.fromSource,
|
||||
toSource: props.definition.target.toRemoteSource,
|
||||
fromTable: props.source.fromTable,
|
||||
toTable: props.definition.target.toRemoteTable,
|
||||
columnMapping: props.definition.detail.columnMapping,
|
||||
editMode: props.isEditMode,
|
||||
});
|
||||
}
|
||||
|
||||
throw Error('Remote Database Relationship not supported');
|
||||
}
|
||||
|
||||
if (isRemoteSchemaRelationshipDefinition(props.definition)) {
|
||||
if (props.sourceCapabilities.isRemoteSchemaRelationshipSupported) {
|
||||
return createRemoteSchemaRelationshipRequestBody({
|
||||
name: props.name,
|
||||
driver: props.driver,
|
||||
fromSource: props.source.fromSource,
|
||||
fromTable: props.source.fromTable,
|
||||
toRemoteSchema: props.definition.target.toRemoteSchema,
|
||||
lhs_fields: props.definition.detail.lhs_fields,
|
||||
remote_field: props.definition.detail.remote_field,
|
||||
editMode: props.isEditMode,
|
||||
});
|
||||
}
|
||||
|
||||
throw Error('Remote Schema Relationship not supported');
|
||||
}
|
||||
|
||||
return 'Not implemented';
|
||||
};
|
||||
|
||||
export const deleteTableRelationshipRequestBody = (
|
||||
props: DeleteRelationshipProps
|
||||
) => {
|
||||
if (props.isRemote)
|
||||
return {
|
||||
type: `${props.driver}_delete_remote_relationship`,
|
||||
args: {
|
||||
source: props.source,
|
||||
table: props.table,
|
||||
name: props.name,
|
||||
},
|
||||
};
|
||||
return {
|
||||
type: `${props.driver}_drop_relationship`,
|
||||
args: {
|
||||
source: props.source,
|
||||
table: props.table,
|
||||
relationship: props.name,
|
||||
},
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user