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
a8806244dc
commit
a343805fee
|
@ -156,6 +156,8 @@
|
||||||
...relateTo,
|
...relateTo,
|
||||||
through: through._id,
|
through: through._id,
|
||||||
fieldName: fromTable.primary[0],
|
fieldName: fromTable.primary[0],
|
||||||
|
throughFrom: relateFrom.throughTo,
|
||||||
|
throughTo: relateFrom.throughFrom,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// the relateFrom.fieldName should remain the same, as it is the foreignKey in the other
|
// the relateFrom.fieldName should remain the same, as it is the foreignKey in the other
|
||||||
|
@ -251,6 +253,22 @@
|
||||||
bind:error={errors.through}
|
bind:error={errors.through}
|
||||||
bind:value={fromRelationship.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}
|
{:else if fromRelationship?.relationshipType && toTable}
|
||||||
<Select
|
<Select
|
||||||
label={`Foreign Key (${toTable?.name})`}
|
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 {
|
} else {
|
||||||
// we're not inserting a doc, will be a bunch of update calls
|
// we're not inserting a doc, will be a bunch of update calls
|
||||||
const isUpdate = !field.through
|
const isUpdate = !field.through
|
||||||
const thisKey: string = isUpdate ? "id" : linkTablePrimary
|
const thisKey: string = isUpdate ? "id" : (field.throughTo || linkTablePrimary)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const otherKey: string = isUpdate ? field.fieldName : tablePrimary
|
const otherKey: string = isUpdate ? field.fieldName : (field.throughFrom || tablePrimary)
|
||||||
row[key].map((relationship: any) => {
|
row[key].map((relationship: any) => {
|
||||||
// we don't really support composite keys for relationships, this is why [0] is used
|
// we don't really support composite keys for relationships, this is why [0] is used
|
||||||
manyRelationships.push({
|
manyRelationships.push({
|
||||||
|
@ -328,12 +328,11 @@ module External {
|
||||||
if (!table.primary || !linkTable.primary) {
|
if (!table.primary || !linkTable.primary) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const definition = {
|
const definition: any = {
|
||||||
// if no foreign key specified then use the name of the field in other table
|
// if no foreign key specified then use the name of the field in other table
|
||||||
from: field.foreignKey || table.primary[0],
|
from: field.foreignKey || table.primary[0],
|
||||||
to: field.fieldName,
|
to: field.fieldName,
|
||||||
tableName: linkTableName,
|
tableName: linkTableName,
|
||||||
through: undefined,
|
|
||||||
// need to specify where to put this back into
|
// need to specify where to put this back into
|
||||||
column: fieldName,
|
column: fieldName,
|
||||||
}
|
}
|
||||||
|
@ -343,8 +342,10 @@ module External {
|
||||||
)
|
)
|
||||||
definition.through = throughTableName
|
definition.through = throughTableName
|
||||||
// don't support composite keys for relationships
|
// don't support composite keys for relationships
|
||||||
definition.from = table.primary[0]
|
definition.from = field.throughFrom || table.primary[0]
|
||||||
definition.to = linkTable.primary[0]
|
definition.to = field.throughTo || linkTable.primary[0]
|
||||||
|
definition.fromPrimary = table.primary[0]
|
||||||
|
definition.toPrimary = linkTable.primary[0]
|
||||||
}
|
}
|
||||||
relationships.push(definition)
|
relationships.push(definition)
|
||||||
}
|
}
|
||||||
|
@ -369,7 +370,8 @@ module External {
|
||||||
}
|
}
|
||||||
const isMany = field.relationshipType === RelationshipTypes.MANY_TO_MANY
|
const isMany = field.relationshipType === RelationshipTypes.MANY_TO_MANY
|
||||||
const tableId = isMany ? field.through : field.tableId
|
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, {
|
const response = await makeExternalQuery(this.appId, {
|
||||||
endpoint: getEndpoint(tableId, DataSourceOperation.READ),
|
endpoint: getEndpoint(tableId, DataSourceOperation.READ),
|
||||||
filters: {
|
filters: {
|
||||||
|
|
|
@ -15,6 +15,8 @@ export interface FieldSchema {
|
||||||
through?: string
|
through?: string
|
||||||
foreignKey?: string
|
foreignKey?: string
|
||||||
autocolumn?: boolean
|
autocolumn?: boolean
|
||||||
|
throughFrom?: string
|
||||||
|
throughTo?: string
|
||||||
constraints?: {
|
constraints?: {
|
||||||
type?: string
|
type?: string
|
||||||
email?: boolean
|
email?: boolean
|
||||||
|
|
|
@ -121,6 +121,8 @@ export interface RelationshipsJson {
|
||||||
through?: string
|
through?: string
|
||||||
from?: string
|
from?: string
|
||||||
to?: string
|
to?: string
|
||||||
|
fromPrimary?: string
|
||||||
|
toPrimary?: string
|
||||||
tableName: string
|
tableName: string
|
||||||
column: string
|
column: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,14 +112,16 @@ function addRelationships(
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
const throughTable = relationship.through
|
const throughTable = relationship.through
|
||||||
|
const fromPrimary = relationship.fromPrimary
|
||||||
|
const toPrimary = relationship.toPrimary
|
||||||
query = query
|
query = query
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
.leftJoin(
|
.leftJoin(
|
||||||
throughTable,
|
throughTable,
|
||||||
`${fromTable}.${from}`,
|
`${fromTable}.${fromPrimary}`,
|
||||||
`${throughTable}.${from}`
|
`${throughTable}.${from}`
|
||||||
)
|
)
|
||||||
.leftJoin(toTable, `${toTable}.${to}`, `${throughTable}.${to}`)
|
.leftJoin(toTable, `${toTable}.${toPrimary}`, `${throughTable}.${to}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return query
|
return query
|
||||||
|
|
Loading…
Reference in New Issue