Skip to content

feat(relationships): include is_one_to_one #628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/lib/PostgresMetaRelationships.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export default class PostgresMetaRelationships {
schema: vtkd.view_schema,
relation: vtkd.view_name,
columns: viewColumns,
is_one_to_one: r.is_one_to_one,
referenced_schema: r.referenced_schema,
referenced_relation: r.referenced_relation,
referenced_columns: r.referenced_columns,
Expand All @@ -104,6 +105,7 @@ export default class PostgresMetaRelationships {
schema: r.schema,
relation: r.relation,
columns: r.columns,
is_one_to_one: r.is_one_to_one,
referenced_schema: tvkd.view_schema,
referenced_relation: tvkd.view_name,
referenced_columns: viewColumns,
Expand All @@ -119,6 +121,7 @@ export default class PostgresMetaRelationships {
schema: vtkd.view_schema,
relation: vtkd.view_name,
columns: viewColumns,
is_one_to_one: r.is_one_to_one,
referenced_schema: tvkd.view_schema,
referenced_relation: tvkd.view_name,
referenced_columns: referencedViewColumns,
Expand Down
22 changes: 21 additions & 1 deletion src/lib/sql/table_relationships.sql
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
-- Adapted from
-- https://github.com/PostgREST/postgrest/blob/f9f0f79fa914ac00c11fbf7f4c558e14821e67e2/src/PostgREST/SchemaCache.hs#L722
WITH
pks_uniques_cols AS (
SELECT
connamespace,
conrelid,
jsonb_agg(column_info.cols) as cols
FROM pg_constraint
JOIN lateral (
SELECT array_agg(cols.attname order by cols.attnum) as cols
FROM ( select unnest(conkey) as col) _
JOIN pg_attribute cols on cols.attrelid = conrelid and cols.attnum = col
) column_info ON TRUE
WHERE
contype IN ('p', 'u') and
connamespace::regnamespace::text <> 'pg_catalog'
GROUP BY connamespace, conrelid
)
SELECT
traint.conname AS foreign_key_name,
ns1.nspname AS schema,
tab.relname AS relation,
column_info.cols AS columns,
ns2.nspname AS referenced_schema,
other.relname AS referenced_relation,
column_info.refs AS referenced_columns
column_info.refs AS referenced_columns,
(column_info.cols IN (SELECT * FROM jsonb_array_elements(pks_uqs.cols))) AS is_one_to_one
FROM pg_constraint traint
JOIN LATERAL (
SELECT
Expand All @@ -21,4 +39,6 @@ JOIN pg_namespace ns1 ON ns1.oid = traint.connamespace
JOIN pg_class tab ON tab.oid = traint.conrelid
JOIN pg_class other ON other.oid = traint.confrelid
JOIN pg_namespace ns2 ON ns2.oid = other.relnamespace
LEFT JOIN pks_uniques_cols pks_uqs ON pks_uqs.connamespace = traint.connamespace AND pks_uqs.conrelid = traint.conrelid
WHERE traint.contype = 'f'
AND traint.conparentid = 0
1 change: 1 addition & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ export const postgresRelationshipSchema = Type.Object({
schema: Type.String(),
relation: Type.String(),
columns: Type.Array(Type.String()),
is_one_to_one: Type.Boolean(),
referenced_schema: Type.String(),
referenced_relation: Type.String(),
referenced_columns: Type.Array(Type.String()),
Expand Down
2 changes: 2 additions & 0 deletions src/server/templates/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export interface Database {
(relationship) => `{
foreignKeyName: ${JSON.stringify(relationship.foreign_key_name)}
columns: ${JSON.stringify(relationship.columns)}
isOneToOne: ${relationship.is_one_to_one}
referencedRelation: ${JSON.stringify(relationship.referenced_relation)}
referencedColumns: ${JSON.stringify(relationship.referenced_columns)}
}`
Expand Down Expand Up @@ -235,6 +236,7 @@ export interface Database {
(relationship) => `{
foreignKeyName: ${JSON.stringify(relationship.foreign_key_name)}
columns: ${JSON.stringify(relationship.columns)}
isOneToOne: ${relationship.is_one_to_one}
referencedRelation: ${JSON.stringify(relationship.referenced_relation)}
referencedColumns: ${JSON.stringify(relationship.referenced_columns)}
}`
Expand Down
5 changes: 5 additions & 0 deletions test/db/00-init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,8 @@ $$;

create or replace function public.polymorphic_function(text) returns void language sql as '';
create or replace function public.polymorphic_function(bool) returns void language sql as '';

create table user_details (
user_id int8 references users(id) primary key,
details text
);
18 changes: 18 additions & 0 deletions test/lib/tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ test('list', async () => {
"target_table_name": "users",
"target_table_schema": "public",
},
{
"constraint_name": "user_details_user_id_fkey",
"source_column_name": "user_id",
"source_schema": "public",
"source_table_name": "user_details",
"target_column_name": "id",
"target_table_name": "users",
"target_table_schema": "public",
},
],
"replica_identity": "DEFAULT",
"rls_enabled": false,
Expand Down Expand Up @@ -176,6 +185,15 @@ test('list without columns', async () => {
"target_table_name": "users",
"target_table_schema": "public",
},
{
"constraint_name": "user_details_user_id_fkey",
"source_column_name": "user_id",
"source_schema": "public",
"source_table_name": "user_details",
"target_column_name": "id",
"target_table_name": "users",
"target_table_schema": "public",
},
],
"replica_identity": "DEFAULT",
"rls_enabled": false,
Expand Down
37 changes: 37 additions & 0 deletions test/server/typegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ test('typegen', async () => {
{
foreignKeyName: "memes_category_fkey"
columns: ["category"]
isOneToOne: false
referencedRelation: "category"
referencedColumns: ["id"]
}
Expand All @@ -87,12 +88,44 @@ test('typegen', async () => {
{
foreignKeyName: "todos_user-id_fkey"
columns: ["user-id"]
isOneToOne: false
referencedRelation: "users"
referencedColumns: ["id"]
},
{
foreignKeyName: "todos_user-id_fkey"
columns: ["user-id"]
isOneToOne: false
referencedRelation: "users_view"
referencedColumns: ["id"]
}
]
}
user_details: {
Row: {
details: string | null
user_id: number
}
Insert: {
details?: string | null
user_id: number
}
Update: {
details?: string | null
user_id?: number
}
Relationships: [
{
foreignKeyName: "user_details_user_id_fkey"
columns: ["user_id"]
isOneToOne: true
referencedRelation: "users"
referencedColumns: ["id"]
},
{
foreignKeyName: "user_details_user_id_fkey"
columns: ["user_id"]
isOneToOne: true
referencedRelation: "users_view"
referencedColumns: ["id"]
}
Expand Down Expand Up @@ -149,12 +182,14 @@ test('typegen', async () => {
{
foreignKeyName: "todos_user-id_fkey"
columns: ["user-id"]
isOneToOne: false
referencedRelation: "users"
referencedColumns: ["id"]
},
{
foreignKeyName: "todos_user-id_fkey"
columns: ["user-id"]
isOneToOne: false
referencedRelation: "users_view"
referencedColumns: ["id"]
}
Expand All @@ -180,12 +215,14 @@ test('typegen', async () => {
{
foreignKeyName: "todos_user-id_fkey"
columns: ["user-id"]
isOneToOne: false
referencedRelation: "users"
referencedColumns: ["id"]
},
{
foreignKeyName: "todos_user-id_fkey"
columns: ["user-id"]
isOneToOne: false
referencedRelation: "users_view"
referencedColumns: ["id"]
}
Expand Down