Skip to content

Commit d51d98b

Browse files
committed
Add as parameter to @Columns
This was allowed with `@Selection` before, so let's restore support for it.
1 parent 3a95b70 commit d51d98b

File tree

5 files changed

+157
-14
lines changed

5 files changed

+157
-14
lines changed

Sources/StructuredQueries/Macros.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public macro Column(
114114
/// - Parameters primaryKey: These columns are the table's composite primary key.
115115
@attached(peer)
116116
public macro Columns(
117-
// as representableType: (any QueryRepresentable.Type)? = nil,
117+
as representableType: (any QueryRepresentable.Type)? = nil,
118118
primaryKey: Bool = false
119119
) =
120120
#externalMacro(

Sources/StructuredQueriesCore/ColumnGroup.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@
44
/// to generate values of this type.
55
@dynamicMemberLookup
66
public struct ColumnGroup<Root: Table, Values: Table>: _TableColumnExpression
7-
where Values.QueryOutput == Values {
7+
where Values.QueryOutput: Table {
88
public typealias Value = Values
99

1010
public var _names: [String] { Values.TableColumns.allColumns.map(\.name) }
1111

1212
public typealias QueryValue = Values
1313

14-
public let keyPath: KeyPath<Root, Values>
14+
public let keyPath: KeyPath<Root, Values.QueryOutput>
1515

16-
public init(keyPath: KeyPath<Root, Values>) {
16+
public init(keyPath: KeyPath<Root, Values.QueryOutput>) {
1717
self.keyPath = keyPath
1818
}
1919

@@ -22,7 +22,7 @@ where Values.QueryOutput == Values {
2222
}
2323

2424
public subscript<Member>(
25-
dynamicMember keyPath: KeyPath<Values.TableColumns, TableColumn<Values, Member>>
25+
dynamicMember keyPath: KeyPath<Values.TableColumns, TableColumn<Values.QueryOutput, Member>>
2626
) -> TableColumn<Root, Member> {
2727
let column = Values.columns[keyPath: keyPath]
2828
return TableColumn<Root, Member>(
@@ -33,7 +33,7 @@ where Values.QueryOutput == Values {
3333
}
3434

3535
public subscript<Member>(
36-
dynamicMember keyPath: KeyPath<Values.TableColumns, GeneratedColumn<Values, Member>>
36+
dynamicMember keyPath: KeyPath<Values.TableColumns, GeneratedColumn<Values.QueryOutput, Member>>
3737
) -> GeneratedColumn<Root, Member> {
3838
let column = Values.columns[keyPath: keyPath]
3939
return GeneratedColumn<Root, Member>(
@@ -44,7 +44,7 @@ where Values.QueryOutput == Values {
4444
}
4545

4646
public subscript<Member>(
47-
dynamicMember keyPath: KeyPath<Values.TableColumns, ColumnGroup<Values, Member>>
47+
dynamicMember keyPath: KeyPath<Values.TableColumns, ColumnGroup<Values.QueryOutput, Member>>
4848
) -> ColumnGroup<Root, Member> {
4949
let column = Values.columns[keyPath: keyPath]
5050
return ColumnGroup<Root, Member>(
@@ -53,12 +53,12 @@ where Values.QueryOutput == Values {
5353
}
5454

5555
public var _allColumns: [any TableColumnExpression] {
56-
Values.TableColumns.allColumns.map { column in
56+
Values.QueryOutput.TableColumns.allColumns.map { column in
5757
func open<R, V>(
5858
_ column: some TableColumnExpression<R, V>
5959
) -> any TableColumnExpression {
6060
let keyPath = keyPath.appending(
61-
path: unsafeDowncast(column.keyPath, to: KeyPath<Values, V.QueryOutput>.self)
61+
path: unsafeDowncast(column.keyPath, to: KeyPath<Values.QueryOutput, V.QueryOutput>.self)
6262
)
6363
return TableColumn<Root, V>(
6464
column.name,
@@ -71,12 +71,12 @@ where Values.QueryOutput == Values {
7171
}
7272

7373
public var _writableColumns: [any WritableTableColumnExpression] {
74-
Values.TableColumns.writableColumns.map { column in
74+
Values.QueryOutput.TableColumns.writableColumns.map { column in
7575
func open<R, V>(
7676
_ column: some WritableTableColumnExpression<R, V>
7777
) -> any WritableTableColumnExpression {
7878
let keyPath = keyPath.appending(
79-
path: unsafeDowncast(column.keyPath, to: KeyPath<Values, V.QueryOutput>.self)
79+
path: unsafeDowncast(column.keyPath, to: KeyPath<Values.QueryOutput, V.QueryOutput>.self)
8080
)
8181
return TableColumn<Root, V>(
8282
column.name,

Sources/StructuredQueriesMacros/TableMacro.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -868,9 +868,9 @@ extension TableMacro: ExtensionMacro {
868868
public typealias From = Swift.Never
869869
""",
870870
])
871-
let columnWidth: ExprSyntax = """
871+
let columnWidth = """
872872
var columnWidth = 0
873-
columnWidth += \(columnWidths, separator: "\ncolumnWidth += ")
873+
columnWidth += \(columnWidths.map(\.description).joined(separator: "\ncolumnWidth += "))
874874
return columnWidth
875875
"""
876876

@@ -881,7 +881,7 @@ extension TableMacro: ExtensionMacro {
881881
\(conformances.isEmpty ? "" : ": \(conformances, separator: ", ")") {\
882882
\(statics, separator: "\n")
883883
public \(nonisolated)static var columns: TableColumns { TableColumns() }
884-
public \(nonisolated)static var _columnWidth: Int { \(columnWidth) }
884+
public \(nonisolated)static var _columnWidth: Int { \(raw: columnWidth) }
885885
public \(nonisolated)static var tableName: String { \(tableName) }\
886886
\(letSchemaName)\(initDecoder)\(initFromOther)
887887
}

Tests/StructuredQueriesMacrosTests/TableMacroTests.swift

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2414,6 +2414,90 @@ extension SnapshotTests {
24142414
}
24152415
}
24162416

2417+
@Test func columnsRepresentation() {
2418+
assertMacro {
2419+
"""
2420+
@Selection
2421+
struct RemindersListAliasAndReminderCount {
2422+
@Columns(as: TableAlias<RemindersList, RL>.self)
2423+
let remindersList: RemindersList
2424+
let remindersCount: Int
2425+
}
2426+
"""
2427+
} expansion: {
2428+
#"""
2429+
struct RemindersListAliasAndReminderCount {
2430+
let remindersList: RemindersList
2431+
let remindersCount: Int
2432+
2433+
public nonisolated struct TableColumns: StructuredQueriesCore.TableDefinition {
2434+
public typealias QueryValue = RemindersListAliasAndReminderCount
2435+
public let remindersList = StructuredQueriesCore.ColumnGroup<QueryValue, TableAlias<RemindersList, RL>>(keyPath: \QueryValue.remindersList)
2436+
public let remindersCount = StructuredQueriesCore._TableColumn<QueryValue, Int>.for("remindersCount", keyPath: \QueryValue.remindersCount)
2437+
public static var allColumns: [any StructuredQueriesCore.TableColumnExpression] {
2438+
var allColumns: [any StructuredQueriesCore.TableColumnExpression] = []
2439+
allColumns.append(contentsOf: QueryValue.columns.remindersList._allColumns)
2440+
allColumns.append(contentsOf: QueryValue.columns.remindersCount._allColumns)
2441+
return allColumns
2442+
}
2443+
public static var writableColumns: [any StructuredQueriesCore.WritableTableColumnExpression] {
2444+
var writableColumns: [any StructuredQueriesCore.WritableTableColumnExpression] = []
2445+
writableColumns.append(contentsOf: QueryValue.columns.remindersList._writableColumns)
2446+
writableColumns.append(contentsOf: QueryValue.columns.remindersCount._writableColumns)
2447+
return writableColumns
2448+
}
2449+
public var queryFragment: QueryFragment {
2450+
"\(self.remindersList), \(self.remindersCount)"
2451+
}
2452+
}
2453+
2454+
public nonisolated struct Selection: StructuredQueriesCore.TableExpression {
2455+
public typealias QueryValue = RemindersListAliasAndReminderCount
2456+
public let allColumns: [any StructuredQueriesCore.QueryExpression]
2457+
public init(
2458+
remindersList: some StructuredQueriesCore.QueryExpression<TableAlias<RemindersList, RL>>,
2459+
remindersCount: some StructuredQueriesCore.QueryExpression<Int>
2460+
) {
2461+
var allColumns: [any StructuredQueriesCore.QueryExpression] = []
2462+
allColumns.append(contentsOf: remindersList._allColumns)
2463+
allColumns.append(contentsOf: remindersCount._allColumns)
2464+
self.allColumns = allColumns
2465+
}
2466+
}
2467+
}
2468+
2469+
nonisolated extension RemindersListAliasAndReminderCount: StructuredQueriesCore.Table, StructuredQueriesCore._Selection, StructuredQueriesCore.PartialSelectStatement {
2470+
public typealias QueryValue = Self
2471+
public typealias From = Swift.Never
2472+
public nonisolated static var columns: TableColumns {
2473+
TableColumns()
2474+
}
2475+
public nonisolated static var _columnWidth: Int {
2476+
var columnWidth = 0
2477+
columnWidth += TableAlias<RemindersList, RL>._columnWidth
2478+
columnWidth += Int._columnWidth
2479+
return columnWidth
2480+
}
2481+
public nonisolated static var tableName: String {
2482+
"remindersListAliasAndReminderCounts"
2483+
}
2484+
public nonisolated init(decoder: inout some StructuredQueriesCore.QueryDecoder) throws {
2485+
let remindersList = try decoder.decode(TableAlias<RemindersList, RL>.self)
2486+
let remindersCount = try decoder.decode(Int.self)
2487+
guard let remindersList else {
2488+
throw StructuredQueriesCore.QueryDecodingError.missingRequiredColumn
2489+
}
2490+
guard let remindersCount else {
2491+
throw StructuredQueriesCore.QueryDecodingError.missingRequiredColumn
2492+
}
2493+
self.remindersList = remindersList
2494+
self.remindersCount = remindersCount
2495+
}
2496+
}
2497+
"""#
2498+
}
2499+
}
2500+
24172501
#if StructuredQueriesCasePaths
24182502
@Test func enumBasics() {
24192503
assertMacro {

Tests/StructuredQueriesTests/SelectionTests.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,56 @@ extension SnapshotTests {
234234
"""
235235
}
236236
}
237+
238+
@Test func alias() {
239+
let baseQuery =
240+
RemindersList.as(RL.self).all
241+
.group(by: \.id)
242+
.limit(2)
243+
.join(Reminder.all) { $0.id.eq($1.remindersListID) }
244+
245+
assertQuery(
246+
baseQuery
247+
.select {
248+
RemindersListAliasAndReminderCount.Columns(
249+
remindersList: $0,
250+
remindersCount: $1.id.count()
251+
)
252+
}
253+
) {
254+
"""
255+
SELECT "rLs"."id" AS "id", "rLs"."color" AS "color", "rLs"."title" AS "title", "rLs"."position" AS "position", count("reminders"."id") AS "remindersCount"
256+
FROM "remindersLists" AS "rLs"
257+
JOIN "reminders" ON ("rLs"."id") = ("reminders"."remindersListID")
258+
GROUP BY "rLs"."id"
259+
LIMIT 2
260+
"""
261+
} results: {
262+
"""
263+
┌─────────────────────────────────────┐
264+
│ RemindersListAliasAndReminderCount( │
265+
│ remindersList: RemindersList( │
266+
│ id: 1, │
267+
│ color: 4889071, │
268+
│ title: "Personal", │
269+
│ position: 0 │
270+
│ ), │
271+
│ remindersCount: 5 │
272+
│ ) │
273+
├─────────────────────────────────────┤
274+
│ RemindersListAliasAndReminderCount( │
275+
│ remindersList: RemindersList( │
276+
│ id: 2, │
277+
│ color: 15567157, │
278+
│ title: "Family", │
279+
│ position: 0 │
280+
│ ), │
281+
│ remindersCount: 3 │
282+
│ ) │
283+
└─────────────────────────────────────┘
284+
"""
285+
}
286+
}
237287
}
238288
}
239289

@@ -254,6 +304,15 @@ struct RemindersListAndReminderCount {
254304
let remindersCount: Int
255305
}
256306

307+
enum RL: AliasName {}
308+
309+
@Selection
310+
struct RemindersListAliasAndReminderCount {
311+
@Columns(as: TableAlias<RemindersList, RL>.self)
312+
let remindersList: RemindersList
313+
let remindersCount: Int
314+
}
315+
257316
@Selection
258317
struct Stats {
259318
let completedCount: Int

0 commit comments

Comments
 (0)