preventing relationship overrides

This commit is contained in:
Martin McKeaveney 2021-07-01 21:24:23 +01:00
parent 0d4c3fd854
commit cae1a20411
4 changed files with 58 additions and 92 deletions

View File

@ -8,10 +8,10 @@
export let from export let from
export let plusTables export let plusTables
export let relationship = {} export let relationship = {}
export let close
let originalName = relationship.name let originalName = relationship.name
$: console.log(relationship)
$: tableOptions = plusTables.map(table => ({ label: table.name, value: table._id })) $: tableOptions = plusTables.map(table => ({ label: table.name, value: table._id }))
$: valid = relationship.name && relationship.tableId && relationship.relationshipType $: valid = relationship.name && relationship.tableId && relationship.relationshipType
$: from = plusTables.find(table => table._id === relationship.source) $: from = plusTables.find(table => table._id === relationship.source)
@ -19,18 +19,6 @@
$: through = plusTables.find(table => table._id === relationship.through) $: through = plusTables.find(table => table._id === relationship.through)
$: linkTable = through || to $: linkTable = through || to
$: relationshipOptions = from && to ? [
{
name: `Many ${from.name} rows → many ${to.name} rows`,
alt: `Many ${from.name} rows → many ${to.name} rows`,
value: RelationshipTypes.MANY_TO_MANY,
},
{
name: `One ${from.name} row → many ${to.name} rows`,
alt: `One ${from.name} rows → many ${to.name} rows`,
value: RelationshipTypes.ONE_TO_MANY,
}
] : []
$: relationshipTypes = [ $: relationshipTypes = [
{ {
@ -51,25 +39,44 @@
// save the relationship on to the datasource // save the relationship on to the datasource
async function saveRelationship() { async function saveRelationship() {
const manyToMany = relationship.relationshipType === RelationshipTypes.MANY_TO_MANY
// source of relationship // source of relationship
datasource.entities[from.name].schema[relationship.name] = { datasource.entities[from.name].schema[relationship.name] = {
type: "link", type: "link",
...relationship ...relationship
} }
// if (originalName !== from.name) {
// delete datasource.entities[from.name].schema[originalName]
// }
// save other side of relationship in the other schema // save other side of relationship in the other schema
datasource.entities[to.name].schema[relationship.name] = { datasource.entities[to.name].schema[relationship.name] = {
name: relationship.name,
type: "link", type: "link",
relationshipType: relationship.relationshipType === RelationshipTypes.MANY_TO_MANY ? RelationshipTypes.MANY_TO_MANY : RelationshipTypes.MANY_TO_ONE, relationshipType: manyToMany ? RelationshipTypes.MANY_TO_MANY : RelationshipTypes.MANY_TO_ONE,
tableId: to._id tableId: from._id,
fieldName: relationship.fieldName,
foreignKey: relationship.foreignKey
} }
// If relationship has been renamed
if (originalName !== relationship.name) {
delete datasource.entities[from.name].schema[originalName]
delete datasource.entities[to.name].schema[originalName]
}
console.log({
from: datasource.entities[from.name].schema[relationship.name],
to: datasource.entities[to.name].schema[relationship.name],
})
await save() await save()
await tables.fetch() await tables.fetch()
} }
async function deleteRelationship() {
delete datasource.entities[from.name].schema[relationship.name]
delete datasource.entities[to.name].schema[relationship.name]
await save()
await tables.fetch()
close()
}
</script> </script>
<ModalContent <ModalContent
@ -108,70 +115,18 @@
/> />
{/if} {/if}
{#if relationship?.relationshipType === RelationshipTypes.ONE_TO_MANY} {#if relationship?.relationshipType === RelationshipTypes.ONE_TO_MANY && to}
<Select <Select
label={"Foreign Key"} label={`Foreign Key (${to.name})`}
options={Object.keys(linkTable.schema)} options={Object.keys(to.schema)}
bind:value={relationship.foreignKey} bind:value={relationship.foreignKey}
/> />
{/if} {/if}
</div>
<!-- <Menu> <div slot="footer">
<MenuSection heading="From"> {#if originalName !== null}
{#each plusTables as table} <Button warning text on:click={deleteRelationship}>Delete</Button>
<MenuItem noClose icon="Table" on:click={() => (relationship.source = table._id)}>
{table.name}
{#if relationship.source === table._id}
<Icon size="S" name="Checkmark" />
{/if}
</MenuItem>
{/each}
</MenuSection>
</Menu> -->
<!-- <Menu>
<MenuSection heading="To">
{#each plusTables as table}
<MenuItem noClose icon="Table" on:click={() => (relationship.tableId = table._id)}>
{table.name}
{#if relationship.tableId === table._id}
<Icon size="S" name="Checkmark" />
{/if}
</MenuItem>
{/each}
</MenuSection>
</Menu> -->
{#if from && to}
<!-- <div class="cardinality">
<RadioGroup
label="Define the relationship"
bind:value={relationship.relationshipType}
on:change={onChangeRelationshipType}
options={relationshipOptions}
getOptionLabel={option => option.name}
getOptionValue={option => option.value}
/>
</div> -->
<!-- <Select
label={`${linkTable.name} Column`}
options={Object.keys(linkTable.schema)}
bind:value={relationship.fieldName}
/> -->
<!-- <div class="table-selector">
<Menu>
<MenuSection heading={`${linkTable.name} Column`}>
{#each Object.keys(linkTable.schema) as column}
<MenuItem noClose icon="Table" on:click={() => (relationship.fieldName = column)}>
{column}
{#if relationship.fieldName === column}
<Icon size="S" name="Checkmark" />
{/if}
</MenuItem>
{/each}
</MenuSection>
</Menu>
</div> -->
{/if} {/if}
</div> </div>

View File

@ -2,6 +2,7 @@
import { goto, beforeUrlChange } from "@roxi/routify" import { goto, beforeUrlChange } from "@roxi/routify"
import { Button, Heading, Body, Divider, Layout, Modal } from "@budibase/bbui" import { Button, Heading, Body, Divider, Layout, Modal } from "@budibase/bbui"
import { datasources, integrations, queries, tables } from "stores/backend" import { datasources, integrations, queries, tables } from "stores/backend"
import { RelationshipTypes } from "constants/backend"
import { notifications } from "@budibase/bbui" import { notifications } from "@budibase/bbui"
import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte" import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte"
import CreateEditRelationship from "./CreateEditRelationship/CreateEditRelationship.svelte" import CreateEditRelationship from "./CreateEditRelationship/CreateEditRelationship.svelte"
@ -66,7 +67,9 @@
} }
function openRelationshipModal(relationship) { function openRelationshipModal(relationship) {
if (relationship.type === "link") {
selectedRelationship = relationship selectedRelationship = relationship
}
relationshipModal.show() relationshipModal.show()
} }
@ -82,7 +85,7 @@
</script> </script>
<Modal bind:this={relationshipModal}> <Modal bind:this={relationshipModal}>
<CreateEditRelationship {datasource} save={saveDatasource} {plusTables} relationship={selectedRelationship} /> <CreateEditRelationship {datasource} save={saveDatasource} close={relationshipModal.hide} {plusTables} relationship={selectedRelationship} />
</Modal> </Modal>
{#if datasource && integration} {#if datasource && integration}
@ -151,7 +154,7 @@
<div class="query-list"> <div class="query-list">
{#each plusTables as table} {#each plusTables as table}
{#each Object.keys(table.schema) as column} {#each Object.keys(table.schema) as column}
{#if table.schema[column].type === "link"} {#if table.schema[column].type === "link" && table.schema[column].relationshipType !== RelationshipTypes.MANY_TO_ONE}
<div <div
class="query-list-item" class="query-list-item"
on:click={() => openRelationshipModal(table.schema[column])}> on:click={() => openRelationshipModal(table.schema[column])}>

View File

@ -13,15 +13,6 @@
"preLaunchTask": "npm: build", "preLaunchTask": "npm: build",
"outFiles": ["${workspaceFolder}/dist/**/*.js"] "outFiles": ["${workspaceFolder}/dist/**/*.js"]
}, },
{
"name": "TS",
"type": "node",
"request": "launch",
"runtimeExecutable": "node",
"runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
"args": ["src/index.ts"],
"cwd": "${workspaceRoot}",
},
{ {
"type": "node", "type": "node",
"request": "launch", "request": "launch",

View File

@ -135,7 +135,10 @@ module PostgresModule {
* Fetches the tables from the postgres table and assigns them to the datasource. * Fetches the tables from the postgres table and assigns them to the datasource.
* @param {*} datasourceId - datasourceId to fetch * @param {*} datasourceId - datasourceId to fetch
*/ */
async buildSchema(datasourceId: string) { async buildSchema(
datasourceId: string,
entities: Record<string, Table>
) {
let tableKeys: { [key: string]: string[] } = {} let tableKeys: { [key: string]: string[] } = {}
try { try {
const primaryKeysResponse = await this.client.query( const primaryKeysResponse = await this.client.query(
@ -167,6 +170,20 @@ module PostgresModule {
name: tableName, name: tableName,
schema: {}, schema: {},
} }
// add the existing relationships from the entities if they exist, to prevent them from being overridden
if (entities) {
const existingTableSchema = entities[tableName].schema
for (let key in existingTableSchema) {
if (existingTableSchema[key].type === "link") {
tables[tableName].schema[key] = existingTableSchema[key]
}
}
console.log({
existingTableSchema,
tables
})
}
} }
const type: string = convertType(column.data_type, TYPE_MAP) const type: string = convertType(column.data_type, TYPE_MAP)