Skip to content

Commit a08764d

Browse files
fix: deterministic ordering of views referencing same table (#903)
* added code, need test * initial migration modification to create users_view_with_multiple_refs_to_users * update tests cases * refactor: Improve relationship sorting with more robust comparison logic * fix test go * chore: simplify referenced_columns comparison --------- Co-authored-by: Bobbie Soedirgo <[email protected]>
1 parent 9f58aa6 commit a08764d

File tree

3 files changed

+244
-2
lines changed

3 files changed

+244
-2
lines changed

src/server/templates/typescript.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ export type Database = {
158158
.sort(
159159
(a, b) =>
160160
a.foreign_key_name.localeCompare(b.foreign_key_name) ||
161-
a.referenced_relation.localeCompare(b.referenced_relation)
161+
a.referenced_relation.localeCompare(b.referenced_relation) ||
162+
JSON.stringify(a.referenced_columns).localeCompare(
163+
JSON.stringify(b.referenced_columns)
164+
)
162165
)
163166
.map(
164167
(relationship) => `{
@@ -235,7 +238,10 @@ export type Database = {
235238
.sort(
236239
(a, b) =>
237240
a.foreign_key_name.localeCompare(b.foreign_key_name) ||
238-
a.referenced_relation.localeCompare(b.referenced_relation)
241+
a.referenced_relation.localeCompare(b.referenced_relation) ||
242+
JSON.stringify(a.referenced_columns).localeCompare(
243+
JSON.stringify(b.referenced_columns)
244+
)
239245
)
240246
.map(
241247
(relationship) => `{

test/db/00-init.sql

+18
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,21 @@ create table table_with_primary_key_other_than_id (
141141
create type composite_type_with_record_attribute as (
142142
todo todos
143143
);
144+
145+
create view users_view_with_multiple_refs_to_users as
146+
WITH initial_user AS (
147+
SELECT
148+
u.id as initial_id,
149+
u.name as initial_name
150+
FROM users u
151+
where u.id = 1
152+
),
153+
second_user AS (
154+
SELECT
155+
u.id as second_id,
156+
u.name as second_name
157+
FROM users u
158+
where u.id = 2
159+
)
160+
SELECT * from initial_user iu
161+
cross join second_user su;

test/server/typegen.ts

+218
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,18 @@ test('typegen: typescript', async () => {
158158
referencedRelation: "users_view"
159159
referencedColumns: ["id"]
160160
},
161+
{
162+
foreignKeyName: "todos_user-id_fkey"
163+
columns: ["user-id"]
164+
referencedRelation: "users_view_with_multiple_refs_to_users"
165+
referencedColumns: ["initial_id"]
166+
},
167+
{
168+
foreignKeyName: "todos_user-id_fkey"
169+
columns: ["user-id"]
170+
referencedRelation: "users_view_with_multiple_refs_to_users"
171+
referencedColumns: ["second_id"]
172+
},
161173
]
162174
}
163175
user_details: {
@@ -192,6 +204,18 @@ test('typegen: typescript', async () => {
192204
referencedRelation: "users_view"
193205
referencedColumns: ["id"]
194206
},
207+
{
208+
foreignKeyName: "user_details_user_id_fkey"
209+
columns: ["user_id"]
210+
referencedRelation: "users_view_with_multiple_refs_to_users"
211+
referencedColumns: ["initial_id"]
212+
},
213+
{
214+
foreignKeyName: "user_details_user_id_fkey"
215+
columns: ["user_id"]
216+
referencedRelation: "users_view_with_multiple_refs_to_users"
217+
referencedColumns: ["second_id"]
218+
},
195219
]
196220
}
197221
users: {
@@ -272,6 +296,18 @@ test('typegen: typescript', async () => {
272296
referencedRelation: "users_view"
273297
referencedColumns: ["id"]
274298
},
299+
{
300+
foreignKeyName: "todos_user-id_fkey"
301+
columns: ["user-id"]
302+
referencedRelation: "users_view_with_multiple_refs_to_users"
303+
referencedColumns: ["initial_id"]
304+
},
305+
{
306+
foreignKeyName: "todos_user-id_fkey"
307+
columns: ["user-id"]
308+
referencedRelation: "users_view_with_multiple_refs_to_users"
309+
referencedColumns: ["second_id"]
310+
},
275311
]
276312
}
277313
todos_view: {
@@ -309,6 +345,18 @@ test('typegen: typescript', async () => {
309345
referencedRelation: "users_view"
310346
referencedColumns: ["id"]
311347
},
348+
{
349+
foreignKeyName: "todos_user-id_fkey"
350+
columns: ["user-id"]
351+
referencedRelation: "users_view_with_multiple_refs_to_users"
352+
referencedColumns: ["initial_id"]
353+
},
354+
{
355+
foreignKeyName: "todos_user-id_fkey"
356+
columns: ["user-id"]
357+
referencedRelation: "users_view_with_multiple_refs_to_users"
358+
referencedColumns: ["second_id"]
359+
},
312360
]
313361
}
314362
users_view: {
@@ -329,6 +377,15 @@ test('typegen: typescript', async () => {
329377
}
330378
Relationships: []
331379
}
380+
users_view_with_multiple_refs_to_users: {
381+
Row: {
382+
initial_id: number | null
383+
initial_name: string | null
384+
second_id: number | null
385+
second_name: string | null
386+
}
387+
Relationships: []
388+
}
332389
}
333390
Functions: {
334391
blurb: {
@@ -713,6 +770,20 @@ test('typegen w/ one-to-one relationships', async () => {
713770
referencedRelation: "users_view"
714771
referencedColumns: ["id"]
715772
},
773+
{
774+
foreignKeyName: "todos_user-id_fkey"
775+
columns: ["user-id"]
776+
isOneToOne: false
777+
referencedRelation: "users_view_with_multiple_refs_to_users"
778+
referencedColumns: ["initial_id"]
779+
},
780+
{
781+
foreignKeyName: "todos_user-id_fkey"
782+
columns: ["user-id"]
783+
isOneToOne: false
784+
referencedRelation: "users_view_with_multiple_refs_to_users"
785+
referencedColumns: ["second_id"]
786+
},
716787
]
717788
}
718789
user_details: {
@@ -750,6 +821,20 @@ test('typegen w/ one-to-one relationships', async () => {
750821
referencedRelation: "users_view"
751822
referencedColumns: ["id"]
752823
},
824+
{
825+
foreignKeyName: "user_details_user_id_fkey"
826+
columns: ["user_id"]
827+
isOneToOne: true
828+
referencedRelation: "users_view_with_multiple_refs_to_users"
829+
referencedColumns: ["initial_id"]
830+
},
831+
{
832+
foreignKeyName: "user_details_user_id_fkey"
833+
columns: ["user_id"]
834+
isOneToOne: true
835+
referencedRelation: "users_view_with_multiple_refs_to_users"
836+
referencedColumns: ["second_id"]
837+
},
753838
]
754839
}
755840
users: {
@@ -833,6 +918,20 @@ test('typegen w/ one-to-one relationships', async () => {
833918
referencedRelation: "users_view"
834919
referencedColumns: ["id"]
835920
},
921+
{
922+
foreignKeyName: "todos_user-id_fkey"
923+
columns: ["user-id"]
924+
isOneToOne: false
925+
referencedRelation: "users_view_with_multiple_refs_to_users"
926+
referencedColumns: ["initial_id"]
927+
},
928+
{
929+
foreignKeyName: "todos_user-id_fkey"
930+
columns: ["user-id"]
931+
isOneToOne: false
932+
referencedRelation: "users_view_with_multiple_refs_to_users"
933+
referencedColumns: ["second_id"]
934+
},
836935
]
837936
}
838937
todos_view: {
@@ -873,6 +972,20 @@ test('typegen w/ one-to-one relationships', async () => {
873972
referencedRelation: "users_view"
874973
referencedColumns: ["id"]
875974
},
975+
{
976+
foreignKeyName: "todos_user-id_fkey"
977+
columns: ["user-id"]
978+
isOneToOne: false
979+
referencedRelation: "users_view_with_multiple_refs_to_users"
980+
referencedColumns: ["initial_id"]
981+
},
982+
{
983+
foreignKeyName: "todos_user-id_fkey"
984+
columns: ["user-id"]
985+
isOneToOne: false
986+
referencedRelation: "users_view_with_multiple_refs_to_users"
987+
referencedColumns: ["second_id"]
988+
},
876989
]
877990
}
878991
users_view: {
@@ -893,6 +1006,15 @@ test('typegen w/ one-to-one relationships', async () => {
8931006
}
8941007
Relationships: []
8951008
}
1009+
users_view_with_multiple_refs_to_users: {
1010+
Row: {
1011+
initial_id: number | null
1012+
initial_name: string | null
1013+
second_id: number | null
1014+
second_name: string | null
1015+
}
1016+
Relationships: []
1017+
}
8961018
}
8971019
Functions: {
8981020
blurb: {
@@ -1277,6 +1399,20 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
12771399
referencedRelation: "users_view"
12781400
referencedColumns: ["id"]
12791401
},
1402+
{
1403+
foreignKeyName: "todos_user-id_fkey"
1404+
columns: ["user-id"]
1405+
isOneToOne: false
1406+
referencedRelation: "users_view_with_multiple_refs_to_users"
1407+
referencedColumns: ["initial_id"]
1408+
},
1409+
{
1410+
foreignKeyName: "todos_user-id_fkey"
1411+
columns: ["user-id"]
1412+
isOneToOne: false
1413+
referencedRelation: "users_view_with_multiple_refs_to_users"
1414+
referencedColumns: ["second_id"]
1415+
},
12801416
]
12811417
}
12821418
user_details: {
@@ -1314,6 +1450,20 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
13141450
referencedRelation: "users_view"
13151451
referencedColumns: ["id"]
13161452
},
1453+
{
1454+
foreignKeyName: "user_details_user_id_fkey"
1455+
columns: ["user_id"]
1456+
isOneToOne: true
1457+
referencedRelation: "users_view_with_multiple_refs_to_users"
1458+
referencedColumns: ["initial_id"]
1459+
},
1460+
{
1461+
foreignKeyName: "user_details_user_id_fkey"
1462+
columns: ["user_id"]
1463+
isOneToOne: true
1464+
referencedRelation: "users_view_with_multiple_refs_to_users"
1465+
referencedColumns: ["second_id"]
1466+
},
13171467
]
13181468
}
13191469
users: {
@@ -1397,6 +1547,20 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
13971547
referencedRelation: "users_view"
13981548
referencedColumns: ["id"]
13991549
},
1550+
{
1551+
foreignKeyName: "todos_user-id_fkey"
1552+
columns: ["user-id"]
1553+
isOneToOne: false
1554+
referencedRelation: "users_view_with_multiple_refs_to_users"
1555+
referencedColumns: ["initial_id"]
1556+
},
1557+
{
1558+
foreignKeyName: "todos_user-id_fkey"
1559+
columns: ["user-id"]
1560+
isOneToOne: false
1561+
referencedRelation: "users_view_with_multiple_refs_to_users"
1562+
referencedColumns: ["second_id"]
1563+
},
14001564
]
14011565
}
14021566
todos_view: {
@@ -1437,6 +1601,20 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
14371601
referencedRelation: "users_view"
14381602
referencedColumns: ["id"]
14391603
},
1604+
{
1605+
foreignKeyName: "todos_user-id_fkey"
1606+
columns: ["user-id"]
1607+
isOneToOne: false
1608+
referencedRelation: "users_view_with_multiple_refs_to_users"
1609+
referencedColumns: ["initial_id"]
1610+
},
1611+
{
1612+
foreignKeyName: "todos_user-id_fkey"
1613+
columns: ["user-id"]
1614+
isOneToOne: false
1615+
referencedRelation: "users_view_with_multiple_refs_to_users"
1616+
referencedColumns: ["second_id"]
1617+
},
14401618
]
14411619
}
14421620
users_view: {
@@ -1457,6 +1635,15 @@ test('typegen: typescript w/ one-to-one relationships', async () => {
14571635
}
14581636
Relationships: []
14591637
}
1638+
users_view_with_multiple_refs_to_users: {
1639+
Row: {
1640+
initial_id: number | null
1641+
initial_name: string | null
1642+
second_id: number | null
1643+
second_name: string | null
1644+
}
1645+
Relationships: []
1646+
}
14601647
}
14611648
Functions: {
14621649
blurb: {
@@ -1853,6 +2040,13 @@ type PublicAViewSelect struct {
18532040
Id *int64 \`json:"id"\`
18542041
}
18552042
2043+
type PublicUsersViewWithMultipleRefsToUsersSelect struct {
2044+
InitialId *int64 \`json:"initial_id"\`
2045+
InitialName *string \`json:"initial_name"\`
2046+
SecondId *int64 \`json:"second_id"\`
2047+
SecondName *string \`json:"second_name"\`
2048+
}
2049+
18562050
type PublicTodosMatviewSelect struct {
18572051
Details *string \`json:"details"\`
18582052
Id *int64 \`json:"id"\`
@@ -2200,6 +2394,18 @@ test('typegen: swift', async () => {
22002394
case status = "status"
22012395
}
22022396
}
2397+
internal struct UsersViewWithMultipleRefsToUsersSelect: Codable, Hashable, Sendable {
2398+
internal let initialId: Int64?
2399+
internal let initialName: String?
2400+
internal let secondId: Int64?
2401+
internal let secondName: String?
2402+
internal enum CodingKeys: String, CodingKey {
2403+
case initialId = "initial_id"
2404+
case initialName = "initial_name"
2405+
case secondId = "second_id"
2406+
case secondName = "second_name"
2407+
}
2408+
}
22032409
internal struct CompositeTypeWithArrayAttribute: Codable, Hashable, Sendable {
22042410
internal let MyTextArray: AnyJSON
22052411
internal enum CodingKeys: String, CodingKey {
@@ -2551,6 +2757,18 @@ test('typegen: swift w/ public access control', async () => {
25512757
case status = "status"
25522758
}
25532759
}
2760+
public struct UsersViewWithMultipleRefsToUsersSelect: Codable, Hashable, Sendable {
2761+
public let initialId: Int64?
2762+
public let initialName: String?
2763+
public let secondId: Int64?
2764+
public let secondName: String?
2765+
public enum CodingKeys: String, CodingKey {
2766+
case initialId = "initial_id"
2767+
case initialName = "initial_name"
2768+
case secondId = "second_id"
2769+
case secondName = "second_name"
2770+
}
2771+
}
25542772
public struct CompositeTypeWithArrayAttribute: Codable, Hashable, Sendable {
25552773
public let MyTextArray: AnyJSON
25562774
public enum CodingKeys: String, CodingKey {

0 commit comments

Comments
 (0)