Skip to content

Commit e4f85f3

Browse files
authored
fix(postgrest): avoid duplicated columns and prefer fields (#463)
1 parent 0667b9f commit e4f85f3

File tree

5 files changed

+46
-9
lines changed

5 files changed

+46
-9
lines changed

Sources/Helpers/HTTP/HTTPRequest.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,13 @@ package enum HTTPMethod: String, Sendable {
6868
case patch = "PATCH"
6969
case options = "OPTIONS"
7070
}
71+
72+
extension [URLQueryItem] {
73+
package mutating func appendOrUpdate(_ queryItem: URLQueryItem) {
74+
if let index = firstIndex(where: { $0.name == queryItem.name }) {
75+
self[index] = queryItem
76+
} else {
77+
self.append(queryItem)
78+
}
79+
}
80+
}

Sources/PostgREST/PostgrestQueryBuilder.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public final class PostgrestQueryBuilder: PostgrestBuilder {
2727
}
2828
.joined(separator: "")
2929

30-
$0.request.query.append(URLQueryItem(name: "select", value: cleanedColumns))
30+
$0.request.query.appendOrUpdate(URLQueryItem(name: "select", value: cleanedColumns))
3131

3232
if let count {
3333
$0.request.headers["Prefer"] = "count=\(count.rawValue)"
@@ -73,7 +73,7 @@ public final class PostgrestQueryBuilder: PostgrestBuilder {
7373
{
7474
let allKeys = jsonObject.flatMap(\.keys)
7575
let uniqueKeys = Set(allKeys).sorted()
76-
$0.request.query.append(URLQueryItem(
76+
$0.request.query.appendOrUpdate(URLQueryItem(
7777
name: "columns",
7878
value: uniqueKeys.joined(separator: ",")
7979
))
@@ -108,7 +108,7 @@ public final class PostgrestQueryBuilder: PostgrestBuilder {
108108
"return=\(returning.rawValue)",
109109
]
110110
if let onConflict {
111-
$0.request.query.append(URLQueryItem(name: "on_conflict", value: onConflict))
111+
$0.request.query.appendOrUpdate(URLQueryItem(name: "on_conflict", value: onConflict))
112112
}
113113
$0.request.body = try configuration.encoder.encode(values)
114114
if let count {
@@ -126,7 +126,7 @@ public final class PostgrestQueryBuilder: PostgrestBuilder {
126126
{
127127
let allKeys = jsonObject.flatMap(\.keys)
128128
let uniqueKeys = Set(allKeys).sorted()
129-
$0.request.query.append(URLQueryItem(
129+
$0.request.query.appendOrUpdate(URLQueryItem(
130130
name: "columns",
131131
value: uniqueKeys.joined(separator: ",")
132132
))

Sources/PostgREST/PostgrestTransformBuilder.swift

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,21 @@ public class PostgrestTransformBuilder: PostgrestBuilder {
2222
}
2323
.joined(separator: "")
2424
mutableState.withValue {
25-
$0.request.query.append(URLQueryItem(name: "select", value: cleanedColumns))
25+
$0.request.query.appendOrUpdate(URLQueryItem(name: "select", value: cleanedColumns))
2626

27-
if $0.request.headers["Prefer"] != nil {
28-
$0.request.headers["Prefer", default: ""] += ","
29-
}
27+
if let prefer = $0.request.headers["Prefer"] {
28+
var components = prefer.components(separatedBy: ",")
29+
30+
if let index = components.firstIndex(where: { $0.hasPrefix("return=") }) {
31+
components[index] = "return=representation"
32+
} else {
33+
components.append("return=representation")
34+
}
3035

31-
$0.request.headers["Prefer", default: ""] += "return=representation"
36+
$0.request.headers["Prefer"] = components.joined(separator: ",")
37+
} else {
38+
$0.request.headers["Prefer"] = "return=representation"
39+
}
3240
}
3341
return self
3442
}

Tests/PostgRESTTests/BuildURLRequestTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,17 @@ final class BuildURLRequestTests: XCTestCase {
141141
]
142142
)
143143
},
144+
TestCase(name: "select after bulk upsert") { client in
145+
try client.from("users")
146+
.upsert(
147+
[
148+
User(email: "[email protected]"),
149+
User(email: "[email protected]"),
150+
],
151+
onConflict: "username"
152+
)
153+
.select()
154+
},
144155
TestCase(name: "test upsert ignoring duplicates") { client in
145156
try client.from("users")
146157
.upsert(User(email: "[email protected]"), ignoreDuplicates: true)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
curl \
2+
--request POST \
3+
--header "Accept: application/json" \
4+
--header "Content-Type: application/json" \
5+
--header "Prefer: resolution=merge-duplicates,return=representation" \
6+
--header "X-Client-Info: postgrest-swift/x.y.z" \
7+
--data "[{\"email\":\"[email protected]\"},{\"email\":\"[email protected]\"}]" \
8+
"https://example.supabase.co/users?columns=email&on_conflict=username&select=*"

0 commit comments

Comments
 (0)