Fix for many to many relationships where the union table has arbituarily named foreign key constraint columns, an example has been provided in the scripts directory.
This commit is contained in:
parent
be7d343868
commit
80e7671444
|
@ -156,6 +156,8 @@
|
|||
...relateTo,
|
||||
through: through._id,
|
||||
fieldName: fromTable.primary[0],
|
||||
throughFrom: relateFrom.throughTo,
|
||||
throughTo: relateFrom.throughFrom,
|
||||
}
|
||||
} else {
|
||||
// the relateFrom.fieldName should remain the same, as it is the foreignKey in the other
|
||||
|
@ -251,6 +253,22 @@
|
|||
bind:error={errors.through}
|
||||
bind:value={fromRelationship.through}
|
||||
/>
|
||||
{#if fromTable && toTable && through}
|
||||
<Select
|
||||
label={`Foreign Key (${fromTable?.name})`}
|
||||
options={Object.keys(through?.schema)}
|
||||
on:change={() => ($touched.fromForeign = true)}
|
||||
bind:error={errors.fromForeign}
|
||||
bind:value={fromRelationship.throughTo}
|
||||
/>
|
||||
<Select
|
||||
label={`Foreign Key (${toTable?.name})`}
|
||||
options={Object.keys(through?.schema)}
|
||||
on:change={() => ($touched.toForeign = true)}
|
||||
bind:error={errors.toForeign}
|
||||
bind:value={fromRelationship.throughFrom}
|
||||
/>
|
||||
{/if}
|
||||
{:else if fromRelationship?.relationshipType && toTable}
|
||||
<Select
|
||||
label={`Foreign Key (${toTable?.name})`}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
version: "3.8"
|
||||
services:
|
||||
db:
|
||||
container_name: postgres
|
||||
image: postgres
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_PASSWORD: root
|
||||
POSTGRES_DB: main
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
#- pg_data:/var/lib/postgresql/data/
|
||||
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
|
||||
pgadmin:
|
||||
container_name: pgadmin-pg
|
||||
image: dpage/pgadmin4
|
||||
restart: always
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: root@root.com
|
||||
PGADMIN_DEFAULT_PASSWORD: root
|
||||
ports:
|
||||
- "5050:80"
|
||||
|
||||
#volumes:
|
||||
# pg_data:
|
|
@ -0,0 +1,41 @@
|
|||
SELECT 'CREATE DATABASE main'
|
||||
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'main')\gexec
|
||||
|
||||
CREATE TABLE categories
|
||||
(
|
||||
name text COLLATE pg_catalog."default",
|
||||
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
|
||||
CONSTRAINT categories_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE customers
|
||||
(
|
||||
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
|
||||
name text COLLATE pg_catalog."default",
|
||||
email text COLLATE pg_catalog."default",
|
||||
age integer,
|
||||
"dateOfBirth" date,
|
||||
CONSTRAINT customers_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE customer_category
|
||||
(
|
||||
customer_id integer,
|
||||
category_id integer,
|
||||
notes text COLLATE pg_catalog."default",
|
||||
id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
|
||||
CONSTRAINT "Category" FOREIGN KEY (category_id)
|
||||
REFERENCES public.categories (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION
|
||||
NOT VALID,
|
||||
CONSTRAINT "Customer" FOREIGN KEY (customer_id)
|
||||
REFERENCES public.customers (id) MATCH SIMPLE
|
||||
ON UPDATE NO ACTION
|
||||
ON DELETE NO ACTION
|
||||
NOT VALID
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO customers (name, email, age) VALUES ('Mike', 'mike@mike.com', 30);
|
||||
INSERT INTO categories (name) VALUES ('Books');
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
docker-compose down
|
||||
docker volume prune -f
|
|
@ -205,9 +205,9 @@ module External {
|
|||
} else {
|
||||
// we're not inserting a doc, will be a bunch of update calls
|
||||
const isUpdate = !field.through
|
||||
const thisKey: string = isUpdate ? "id" : linkTablePrimary
|
||||
const thisKey: string = isUpdate ? "id" : (field.throughTo || linkTablePrimary)
|
||||
// @ts-ignore
|
||||
const otherKey: string = isUpdate ? field.fieldName : tablePrimary
|
||||
const otherKey: string = isUpdate ? field.fieldName : (field.throughFrom || tablePrimary)
|
||||
row[key].map((relationship: any) => {
|
||||
// we don't really support composite keys for relationships, this is why [0] is used
|
||||
manyRelationships.push({
|
||||
|
@ -328,12 +328,11 @@ module External {
|
|||
if (!table.primary || !linkTable.primary) {
|
||||
continue
|
||||
}
|
||||
const definition = {
|
||||
const definition: any = {
|
||||
// if no foreign key specified then use the name of the field in other table
|
||||
from: field.foreignKey || table.primary[0],
|
||||
to: field.fieldName,
|
||||
tableName: linkTableName,
|
||||
through: undefined,
|
||||
// need to specify where to put this back into
|
||||
column: fieldName,
|
||||
}
|
||||
|
@ -343,8 +342,10 @@ module External {
|
|||
)
|
||||
definition.through = throughTableName
|
||||
// don't support composite keys for relationships
|
||||
definition.from = table.primary[0]
|
||||
definition.to = linkTable.primary[0]
|
||||
definition.from = field.throughFrom || table.primary[0]
|
||||
definition.to = field.throughTo || linkTable.primary[0]
|
||||
definition.fromPrimary = table.primary[0]
|
||||
definition.toPrimary = linkTable.primary[0]
|
||||
}
|
||||
relationships.push(definition)
|
||||
}
|
||||
|
@ -369,7 +370,8 @@ module External {
|
|||
}
|
||||
const isMany = field.relationshipType === RelationshipTypes.MANY_TO_MANY
|
||||
const tableId = isMany ? field.through : field.tableId
|
||||
const fieldName = isMany ? primaryKey : field.fieldName
|
||||
const manyKey = field.throughFrom || primaryKey
|
||||
const fieldName = isMany ? manyKey : field.fieldName
|
||||
const response = await makeExternalQuery(this.appId, {
|
||||
endpoint: getEndpoint(tableId, DataSourceOperation.READ),
|
||||
filters: {
|
||||
|
|
|
@ -15,6 +15,8 @@ export interface FieldSchema {
|
|||
through?: string
|
||||
foreignKey?: string
|
||||
autocolumn?: boolean
|
||||
throughFrom?: string
|
||||
throughTo?: string
|
||||
constraints?: {
|
||||
type?: string
|
||||
email?: boolean
|
||||
|
|
|
@ -121,6 +121,8 @@ export interface RelationshipsJson {
|
|||
through?: string
|
||||
from?: string
|
||||
to?: string
|
||||
fromPrimary?: string
|
||||
toPrimary?: string
|
||||
tableName: string
|
||||
column: string
|
||||
}
|
||||
|
|
|
@ -112,14 +112,16 @@ function addRelationships(
|
|||
)
|
||||
} else {
|
||||
const throughTable = relationship.through
|
||||
const fromPrimary = relationship.fromPrimary
|
||||
const toPrimary = relationship.toPrimary
|
||||
query = query
|
||||
// @ts-ignore
|
||||
.leftJoin(
|
||||
throughTable,
|
||||
`${fromTable}.${from}`,
|
||||
`${fromTable}.${fromPrimary}`,
|
||||
`${throughTable}.${from}`
|
||||
)
|
||||
.leftJoin(toTable, `${toTable}.${to}`, `${throughTable}.${to}`)
|
||||
.leftJoin(toTable, `${toTable}.${toPrimary}`, `${throughTable}.${to}`)
|
||||
}
|
||||
}
|
||||
return query
|
||||
|
|
Loading…
Reference in New Issue