Skip to content

Commit 3b9c37e

Browse files
committed
wip
1 parent f0cc943 commit 3b9c37e

File tree

2 files changed

+37
-17
lines changed

2 files changed

+37
-17
lines changed

Sources/StructuredQueriesCore/SQLite/JSONFunctions.swift

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,32 @@ extension PrimaryKeyedTableDefinition where QueryValue: Codable & Sendable {
110110
filter: filter?.queryFragment
111111
)
112112
}
113+
}
114+
115+
116+
extension PrimaryKeyedTableDefinition {
117+
public func jsonGroupArray<Wrapped: Codable & Sendable>(
118+
isDistinct: Bool = false,
119+
order: (some QueryExpression)? = Bool?.none,
120+
filter: (some QueryExpression<Bool>)? = Bool?.none
121+
) -> some QueryExpression<[Wrapped].JSONRepresentation>
122+
where QueryValue == Wrapped?
123+
{
124+
let filterQueryFragment = if let filter {
125+
self.primaryKey.isNot(nil).and(filter).queryFragment
126+
} else {
127+
self.primaryKey.isNot(nil).queryFragment
128+
}
129+
return AggregateFunction(
130+
"json_group_array",
131+
isDistinct: isDistinct,
132+
[jsonObject.queryFragment],
133+
order: order?.queryFragment,
134+
filter: filterQueryFragment
135+
)
136+
}
113137

114-
private var jsonObject: some QueryExpression<QueryValue> {
138+
fileprivate var jsonObject: some QueryExpression<QueryValue> {
115139
func open<TableColumn: TableColumnExpression>(_ column: TableColumn) -> QueryFragment {
116140
typealias Value = TableColumn.QueryValue._Optionalized.Wrapped
117141

@@ -143,8 +167,8 @@ extension PrimaryKeyedTableDefinition where QueryValue: Codable & Sendable {
143167
} else if Value.self == Date.JulianDayRepresentation.self {
144168
return "\(quote: column.name, delimiter: .text), datetime(\(column), 'julianday')"
145169
} else if let codableType = TableColumn.QueryValue.QueryOutput.self
146-
as? any (Codable & Sendable).Type,
147-
isJSONRepresentation(codableType)
170+
as? any (Codable & Sendable).Type,
171+
isJSONRepresentation(codableType)
148172
{
149173
return "\(quote: column.name, delimiter: .text), json(\(column))"
150174
} else {

Tests/StructuredQueriesTests/JSONFunctionsTests.swift

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -136,21 +136,21 @@ extension SnapshotTests {
136136
ReminderRow.Columns(
137137
assignedUser: user,
138138
reminder: reminder,
139-
tags: #sql("\(tag.jsonGroupArray())")
139+
tags: tag.jsonGroupArray()
140140
)
141141
}
142142
.limit(2)
143143
) {
144144
"""
145-
SELECT "users"."id", "users"."name" AS "assignedUser", "reminders"."id", "reminders"."assignedUserID", "reminders"."dueDate", "reminders"."isCompleted", "reminders"."isFlagged", "reminders"."notes", "reminders"."priority", "reminders"."remindersListID", "reminders"."title" AS "reminder", json_group_array(CASE WHEN ("tags"."id" IS NOT NULL) THEN json_object('id', json_quote("tags"."id"), 'title', json_quote("tags"."title")) END) AS "tags"
145+
SELECT "users"."id", "users"."name" AS "assignedUser", "reminders"."id", "reminders"."assignedUserID", "reminders"."dueDate", "reminders"."isCompleted", "reminders"."isFlagged", "reminders"."notes", "reminders"."priority", "reminders"."remindersListID", "reminders"."title" AS "reminder", json_group_array(CASE WHEN ("tags"."id" IS NOT NULL) THEN json_object('id', json_quote("tags"."id"), 'title', json_quote("tags"."title")) END) FILTER (WHERE ("tags"."id" IS NOT NULL)) AS "tags"
146146
FROM "reminders"
147147
LEFT JOIN "remindersTags" ON ("reminders"."id" = "remindersTags"."reminderID")
148148
LEFT JOIN "tags" ON ("remindersTags"."tagID" = "tags"."id")
149149
LEFT JOIN "users" ON ("reminders"."assignedUserID" = "users"."id")
150150
GROUP BY "reminders"."id"
151151
LIMIT 2
152152
"""
153-
} results: {
153+
}results: {
154154
"""
155155
┌──────────────────────────────────────────────┐
156156
│ ReminderRow( │
@@ -214,26 +214,22 @@ extension SnapshotTests {
214214
assertQuery(
215215
RemindersList
216216
.group(by: \.id)
217-
.leftJoin(Milestone.all) { $0.id.eq($2.remindersListID) }
218-
.leftJoin(Reminder.incomplete) { $0.id.eq($1.remindersListID) }
219-
.select { remindersList, milestone, reminder in
217+
.leftJoin(Milestone.all) { $0.id.eq($1.remindersListID) }
218+
.leftJoin(Reminder.incomplete) { $0.id.eq($2.remindersListID) }
219+
.select {
220220
RemindersListRow.Columns(
221-
remindersList: remindersList,
222-
milestones: #sql(
223-
"\(milestone.jsonGroupArray(isDistinct: true, filter: milestone.id.isNot(nil)))"
224-
),
225-
reminders: #sql(
226-
"\(reminder.jsonGroupArray(isDistinct: true, filter: reminder.id.isNot(nil)))"
227-
)
221+
remindersList: $0,
222+
milestones: $1.jsonGroupArray(isDistinct: true),
223+
reminders: $2.jsonGroupArray(isDistinct: true)
228224
)
229225
}
230226
.limit(1)
231227
) {
232228
"""
233229
SELECT "remindersLists"."id", "remindersLists"."color", "remindersLists"."title" AS "remindersList", json_group_array(DISTINCT CASE WHEN ("milestones"."id" IS NOT NULL) THEN json_object('id', json_quote("milestones"."id"), 'remindersListID', json_quote("milestones"."remindersListID"), 'title', json_quote("milestones"."title")) END) FILTER (WHERE ("milestones"."id" IS NOT NULL)) AS "milestones", json_group_array(DISTINCT CASE WHEN ("reminders"."id" IS NOT NULL) THEN json_object('id', json_quote("reminders"."id"), 'assignedUserID', json_quote("reminders"."assignedUserID"), 'dueDate', json_quote("reminders"."dueDate"), 'isCompleted', json(CASE "reminders"."isCompleted" WHEN 0 THEN 'false' WHEN 1 THEN 'true' END), 'isFlagged', json(CASE "reminders"."isFlagged" WHEN 0 THEN 'false' WHEN 1 THEN 'true' END), 'notes', json_quote("reminders"."notes"), 'priority', json_quote("reminders"."priority"), 'remindersListID', json_quote("reminders"."remindersListID"), 'title', json_quote("reminders"."title")) END) FILTER (WHERE ("reminders"."id" IS NOT NULL)) AS "reminders"
234230
FROM "remindersLists"
235-
LEFT JOIN "reminders" ON ("remindersLists"."id" = "reminders"."remindersListID")
236231
LEFT JOIN "milestones" ON ("remindersLists"."id" = "milestones"."remindersListID")
232+
LEFT JOIN "reminders" ON ("remindersLists"."id" = "reminders"."remindersListID")
237233
WHERE NOT ("reminders"."isCompleted")
238234
GROUP BY "remindersLists"."id"
239235
LIMIT 1

0 commit comments

Comments
 (0)