Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.

Commit ac6165c

Browse files
committed
fix: errors with relationships duplicates
1 parent 7298b54 commit ac6165c

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

src/select-query-parser/utils.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@ type FilterRelationNodes<Nodes extends Node[]> = UnionToArray<
3737
}[number]
3838
>
3939

40+
/*
41+
** Because of pg-meta types generation there is some cases where a same relationship can be duplicated
42+
** if the relation is across schemas and views this ensure that we dedup those relations and treat them
43+
** as postgrest would.
44+
** TODO: This is necessary to allow the check for required desambiguation but shouldn't if the
45+
** generated relationships were correct pointing out that each realation is actually toward a different schema
46+
*/
47+
export type DeduplicateRelationships<T extends readonly unknown[]> = T extends readonly [
48+
infer First,
49+
...infer Rest
50+
]
51+
? First extends Rest[number]
52+
? DeduplicateRelationships<Rest extends readonly unknown[] ? Rest : []>
53+
: [First, ...DeduplicateRelationships<Rest extends readonly unknown[] ? Rest : []>]
54+
: T
55+
4056
export type ResolveRelationships<
4157
Schema extends GenericSchema,
4258
RelationName extends string,
@@ -110,7 +126,7 @@ export type CheckDuplicateEmbededReference<
110126
RelationsNodes
111127
> extends infer ResolvedRels
112128
? ResolvedRels extends unknown[]
113-
? FindDuplicates<ResolvedRels> extends infer Duplicates
129+
? FindDuplicates<DeduplicateRelationships<ResolvedRels>> extends infer Duplicates
114130
? Duplicates extends never
115131
? false
116132
: Duplicates extends { fieldName: infer FieldName extends string }
@@ -127,7 +143,7 @@ export type CheckDuplicateEmbededReference<
127143
* Returns a boolean representing whether there is a foreign key referencing
128144
* a given relation.
129145
*/
130-
type HasFKeyToFRel<FRelName, Relationships> = Relationships extends [infer R]
146+
export type HasFKeyToFRel<FRelName, Relationships> = Relationships extends [infer R]
131147
? R extends { referencedRelation: FRelName }
132148
? true
133149
: false
@@ -139,7 +155,7 @@ type HasFKeyToFRel<FRelName, Relationships> = Relationships extends [infer R]
139155
/**
140156
* Checks if there is more than one relation to a given foreign relation name in the Relationships.
141157
*/
142-
type HasMultipleFKeysToFRel<FRelName, Relationships> = Relationships extends [
158+
export type HasMultipleFKeysToFRel<FRelName, Relationships> = Relationships extends [
143159
infer R,
144160
...infer Rest
145161
]
@@ -166,7 +182,10 @@ type CheckRelationshipError<
166182
direction: 'reverse'
167183
}
168184
? // We check if there is possible confusion with other relations with this table
169-
HasMultipleFKeysToFRel<RelatedRelationName, Relationships> extends true
185+
HasMultipleFKeysToFRel<
186+
RelatedRelationName,
187+
DeduplicateRelationships<Relationships>
188+
> extends true
170189
? // If there is, postgrest will fail at runtime, and require desambiguation via hinting
171190
RequireHintingSelectQueryError<
172191
RelatedRelationName,
@@ -184,7 +203,7 @@ type CheckRelationshipError<
184203
}
185204
? HasMultipleFKeysToFRel<
186205
RelatedRelationName,
187-
TablesAndViews<Schema>[From]['Relationships']
206+
DeduplicateRelationships<TablesAndViews<Schema>[From]['Relationships']>
188207
> extends true
189208
? RequireHintingSelectQueryError<From extends string ? From : 'unknown', RelatedRelationName>
190209
: FoundRelation
@@ -236,7 +255,10 @@ type ResolveReverseRelationship<
236255
from: CurrentTableOrView
237256
}
238257
: // If the relation was found via implicit relation naming, we must ensure there is no conflicting matches
239-
HasMultipleFKeysToFRel<RelatedRelationName, Relationships> extends true
258+
HasMultipleFKeysToFRel<
259+
RelatedRelationName,
260+
DeduplicateRelationships<Relationships>
261+
> extends true
240262
? RequireHintingSelectQueryError<
241263
RelatedRelationName,
242264
CurrentTableOrView extends string ? CurrentTableOrView : 'unknown'

test/select-query-parser/types.test-d.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import { expectType } from 'tsd'
99
import { TypeEqual } from 'ts-expect'
1010
import {
11+
DeduplicateRelationships,
1112
FindMatchingRelationships,
1213
FindMatchingTableRelationships,
1314
IsRelationNullable,
@@ -178,3 +179,56 @@ import { ParseQuery } from '../../src/select-query-parser/parser/parser'
178179
type r2 = ProcessNodes<Schema, Row, RelationName, Relationships, ParsedQuery>
179180
expectType<r2>(expected!)
180181
}
182+
183+
// Deduplicate exact sames relationships
184+
{
185+
type rels = [
186+
{
187+
foreignKeyName: 'test_fkey'
188+
columns: ['project_id']
189+
referencedRelation: 'project_subscriptions'
190+
referencedColumns: ['project_id']
191+
},
192+
{
193+
foreignKeyName: 'test_fkey'
194+
columns: ['project_id']
195+
referencedRelation: 'projects'
196+
referencedColumns: ['id']
197+
},
198+
{
199+
foreignKeyName: 'test_fkey'
200+
columns: ['project_id']
201+
referencedRelation: 'projects'
202+
referencedColumns: ['id']
203+
},
204+
{
205+
foreignKeyName: 'test_fkey'
206+
columns: ['project_id']
207+
referencedRelation: 'sls_physical_backups_monitoring'
208+
referencedColumns: ['project_id']
209+
}
210+
]
211+
type expected = [
212+
{
213+
foreignKeyName: 'test_fkey'
214+
columns: ['project_id']
215+
referencedRelation: 'project_subscriptions'
216+
referencedColumns: ['project_id']
217+
},
218+
{
219+
foreignKeyName: 'test_fkey'
220+
columns: ['project_id']
221+
referencedRelation: 'projects'
222+
referencedColumns: ['id']
223+
},
224+
{
225+
foreignKeyName: 'test_fkey'
226+
columns: ['project_id']
227+
referencedRelation: 'sls_physical_backups_monitoring'
228+
referencedColumns: ['project_id']
229+
}
230+
]
231+
232+
type result = DeduplicateRelationships<rels>
233+
expectType<TypeEqual<result, expected>>(true)
234+
}

0 commit comments

Comments
 (0)