diff --git a/src/server/templates/typescript.ts b/src/server/templates/typescript.ts index 4b647034..a46143a4 100644 --- a/src/server/templates/typescript.ts +++ b/src/server/templates/typescript.ts @@ -158,7 +158,10 @@ export type Database = { .sort( (a, b) => a.foreign_key_name.localeCompare(b.foreign_key_name) || - a.referenced_relation.localeCompare(b.referenced_relation) + a.referenced_relation.localeCompare(b.referenced_relation) || + JSON.stringify(a.referenced_columns).localeCompare( + JSON.stringify(b.referenced_columns) + ) ) .map( (relationship) => `{ @@ -235,7 +238,10 @@ export type Database = { .sort( (a, b) => a.foreign_key_name.localeCompare(b.foreign_key_name) || - a.referenced_relation.localeCompare(b.referenced_relation) + a.referenced_relation.localeCompare(b.referenced_relation) || + JSON.stringify(a.referenced_columns).localeCompare( + JSON.stringify(b.referenced_columns) + ) ) .map( (relationship) => `{ diff --git a/test/db/00-init.sql b/test/db/00-init.sql index 07fdecfe..5dec1082 100644 --- a/test/db/00-init.sql +++ b/test/db/00-init.sql @@ -141,3 +141,21 @@ create table table_with_primary_key_other_than_id ( create type composite_type_with_record_attribute as ( todo todos ); + +create view users_view_with_multiple_refs_to_users as +WITH initial_user AS ( + SELECT + u.id as initial_id, + u.name as initial_name + FROM users u + where u.id = 1 +), +second_user AS ( + SELECT + u.id as second_id, + u.name as second_name + FROM users u + where u.id = 2 +) +SELECT * from initial_user iu +cross join second_user su; diff --git a/test/server/typegen.ts b/test/server/typegen.ts index aa8aadb5..65310f2e 100644 --- a/test/server/typegen.ts +++ b/test/server/typegen.ts @@ -158,6 +158,18 @@ test('typegen: typescript', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } user_details: { @@ -192,6 +204,18 @@ test('typegen: typescript', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "user_details_user_id_fkey" + columns: ["user_id"] + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "user_details_user_id_fkey" + columns: ["user_id"] + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } users: { @@ -272,6 +296,18 @@ test('typegen: typescript', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } todos_view: { @@ -309,6 +345,18 @@ test('typegen: typescript', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } users_view: { @@ -329,6 +377,15 @@ test('typegen: typescript', async () => { } Relationships: [] } + users_view_with_multiple_refs_to_users: { + Row: { + initial_id: number | null + initial_name: string | null + second_id: number | null + second_name: string | null + } + Relationships: [] + } } Functions: { blurb: { @@ -713,6 +770,20 @@ test('typegen w/ one-to-one relationships', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } user_details: { @@ -750,6 +821,20 @@ test('typegen w/ one-to-one relationships', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "user_details_user_id_fkey" + columns: ["user_id"] + isOneToOne: true + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "user_details_user_id_fkey" + columns: ["user_id"] + isOneToOne: true + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } users: { @@ -833,6 +918,20 @@ test('typegen w/ one-to-one relationships', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } todos_view: { @@ -873,6 +972,20 @@ test('typegen w/ one-to-one relationships', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } users_view: { @@ -893,6 +1006,15 @@ test('typegen w/ one-to-one relationships', async () => { } Relationships: [] } + users_view_with_multiple_refs_to_users: { + Row: { + initial_id: number | null + initial_name: string | null + second_id: number | null + second_name: string | null + } + Relationships: [] + } } Functions: { blurb: { @@ -1277,6 +1399,20 @@ test('typegen: typescript w/ one-to-one relationships', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } user_details: { @@ -1314,6 +1450,20 @@ test('typegen: typescript w/ one-to-one relationships', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "user_details_user_id_fkey" + columns: ["user_id"] + isOneToOne: true + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "user_details_user_id_fkey" + columns: ["user_id"] + isOneToOne: true + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } users: { @@ -1397,6 +1547,20 @@ test('typegen: typescript w/ one-to-one relationships', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } todos_view: { @@ -1437,6 +1601,20 @@ test('typegen: typescript w/ one-to-one relationships', async () => { referencedRelation: "users_view" referencedColumns: ["id"] }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["initial_id"] + }, + { + foreignKeyName: "todos_user-id_fkey" + columns: ["user-id"] + isOneToOne: false + referencedRelation: "users_view_with_multiple_refs_to_users" + referencedColumns: ["second_id"] + }, ] } users_view: { @@ -1457,6 +1635,15 @@ test('typegen: typescript w/ one-to-one relationships', async () => { } Relationships: [] } + users_view_with_multiple_refs_to_users: { + Row: { + initial_id: number | null + initial_name: string | null + second_id: number | null + second_name: string | null + } + Relationships: [] + } } Functions: { blurb: { @@ -1853,6 +2040,13 @@ type PublicAViewSelect struct { Id *int64 \`json:"id"\` } +type PublicUsersViewWithMultipleRefsToUsersSelect struct { + InitialId *int64 \`json:"initial_id"\` + InitialName *string \`json:"initial_name"\` + SecondId *int64 \`json:"second_id"\` + SecondName *string \`json:"second_name"\` +} + type PublicTodosMatviewSelect struct { Details *string \`json:"details"\` Id *int64 \`json:"id"\` @@ -2200,6 +2394,18 @@ test('typegen: swift', async () => { case status = "status" } } + internal struct UsersViewWithMultipleRefsToUsersSelect: Codable, Hashable, Sendable { + internal let initialId: Int64? + internal let initialName: String? + internal let secondId: Int64? + internal let secondName: String? + internal enum CodingKeys: String, CodingKey { + case initialId = "initial_id" + case initialName = "initial_name" + case secondId = "second_id" + case secondName = "second_name" + } + } internal struct CompositeTypeWithArrayAttribute: Codable, Hashable, Sendable { internal let MyTextArray: AnyJSON internal enum CodingKeys: String, CodingKey { @@ -2551,6 +2757,18 @@ test('typegen: swift w/ public access control', async () => { case status = "status" } } + public struct UsersViewWithMultipleRefsToUsersSelect: Codable, Hashable, Sendable { + public let initialId: Int64? + public let initialName: String? + public let secondId: Int64? + public let secondName: String? + public enum CodingKeys: String, CodingKey { + case initialId = "initial_id" + case initialName = "initial_name" + case secondId = "second_id" + case secondName = "second_name" + } + } public struct CompositeTypeWithArrayAttribute: Codable, Hashable, Sendable { public let MyTextArray: AnyJSON public enum CodingKeys: String, CodingKey {