Skip to content

Commit 93e4379

Browse files
committed
wip
1 parent 0465e23 commit 93e4379

File tree

13 files changed

+246
-1127
lines changed

13 files changed

+246
-1127
lines changed

Sources/StructuredQueries/Macros.swift

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import StructuredQueriesCore
22

33
/// Defines and implements a conformance to the ``/StructuredQueriesCore/Table`` protocol.
44
///
5-
/// - Parameter name: The table's name. Defaults to a lower-camel-case pluralization of the type,
6-
/// _e.g._ `RemindersList` becomes `"remindersLists"`.
5+
/// - Parameters
6+
/// - name: The table's name. Defaults to a lower-camel-case pluralization of the type,
7+
/// _e.g._ `RemindersList` becomes `"remindersLists"`.
8+
/// - schemaName: The table's schema name.
79
@attached(
810
extension,
911
conformances: Table,
@@ -29,6 +31,63 @@ public macro Table(
2931
type: "TableMacro"
3032
)
3133

34+
/// Defines a "selection" of columns that can be decoded from a query.
35+
///
36+
/// When selecting tables and fields from a query, this data is bundled up into a tuple:
37+
///
38+
/// ```swift
39+
/// RemindersList
40+
/// .group(by: \.id)
41+
/// .join(Reminder.all) { $0.id == $0.remindersListID }
42+
/// .select { ($0, $1.count()) }
43+
/// // [(RemindersList, Int)]
44+
/// ```
45+
///
46+
/// The `@Selection` macro allows you to bundle this data up into a dedicated type, instead:
47+
///
48+
/// ```swift
49+
/// @Selection
50+
/// struct ListWithCount {
51+
/// let list: RemindersList
52+
/// let count: Int
53+
/// }
54+
///
55+
/// RemindersList
56+
/// .group(by: \.id)
57+
/// .join(Reminder.all) { $0.id == $0.remindersListID }
58+
/// .select { ListWithCount.Columns(list: $0, count: $1.count()) }
59+
/// // [RemindersListWithReminderCount]
60+
/// ```
61+
///
62+
/// > Tip: `@Selection`s can also be used to build up common table expressions.
63+
///
64+
/// - Parameter name: The selection's name, _i.e._ for a common table expression. Defaults to a
65+
/// lower-camel-case pluralization of the type, _e.g._ `RemindersList` becomes `"remindersLists"`.
66+
@attached(
67+
extension,
68+
conformances: _Selection,
69+
Table,
70+
PartialSelectStatement,
71+
PrimaryKeyedTable,
72+
names: named(From),
73+
named(columns),
74+
named(columnWidth),
75+
named(init(_:)),
76+
named(init(decoder:)),
77+
named(QueryValue),
78+
named(schemaName),
79+
named(tableName)
80+
)
81+
@attached(member, names: named(Draft), named(Selection), named(TableColumns))
82+
@attached(memberAttribute)
83+
public macro Selection(
84+
_ name: String = ""
85+
) =
86+
#externalMacro(
87+
module: "StructuredQueriesMacros",
88+
type: "TableMacro"
89+
)
90+
3291
/// Customizes a column generated by the ``/StructuredQueriesCore/Table`` protocol.
3392
///
3493
/// - Parameters:
@@ -73,53 +132,6 @@ public macro Ephemeral() =
73132
type: "EphemeralMacro"
74133
)
75134

76-
/// Defines the ability for a type to be selected from a query.
77-
///
78-
/// When selecting tables and fields from a query, this data is bundled up into a tuple:
79-
///
80-
/// ```swift
81-
/// RemindersList
82-
/// .group(by: \.id)
83-
/// .join(Reminder.all) { $0.id == $0.remindersListID }
84-
/// .select { ($0, $1.count()) }
85-
/// // [(RemindersList, Int)]
86-
/// ```
87-
///
88-
/// The `@Selection` macro allows you to bundle this data up into a dedicated type, instead:
89-
///
90-
/// ```swift
91-
/// @Selection
92-
/// struct ListWithCount {
93-
/// let list: RemindersList
94-
/// let count: Int
95-
/// }
96-
///
97-
/// RemindersList
98-
/// .group(by: \.id)
99-
/// .join(Reminder.all) { $0.id == $0.remindersListID }
100-
/// .select { ListWithCount.Columns(list: $0, count: $1.count()) }
101-
/// // [RemindersListWithReminderCount]
102-
/// ```
103-
///
104-
/// The ``Table(_:)`` and `@Selection` macros can be composed together to describe a virtual table
105-
/// or common table expression.
106-
@attached(
107-
extension,
108-
conformances: _Selection,
109-
names: named(Columns),
110-
named(init(decoder:))
111-
)
112-
@attached(member, names: named(Columns))
113-
@available(iOS, deprecated: 9999, renamed: "Table")
114-
@available(macOS, deprecated: 9999, renamed: "Table")
115-
@available(tvOS, deprecated: 9999, renamed: "Table")
116-
@available(watchOS, deprecated: 9999, renamed: "Table")
117-
public macro Selection() =
118-
#externalMacro(
119-
module: "StructuredQueriesMacros",
120-
type: "SelectionMacro"
121-
)
122-
123135
/// Explicitly bind a value to a query.
124136
///
125137
/// This macro explicitly binds a Swift value to a query. This is required when binding a value with

Sources/StructuredQueriesCore/Statements/Insert.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,13 +1013,6 @@ public enum InsertValuesBuilder<Value> {
10131013
return [valueFragment]
10141014
}
10151015

1016-
public static func buildExpression(
1017-
_ expression: Value.Columns
1018-
) -> [[QueryFragment]]
1019-
where Value: _Selection {
1020-
[expression.selection.map(\.expression)]
1021-
}
1022-
10231016
public static func buildExpression(
10241017
_ expression: Value.Selection
10251018
) -> [[QueryFragment]]

Sources/StructuredQueriesCore/Table.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public protocol Table: QueryRepresentable, PartialSelectStatement {
5959
static var all: DefaultScope { get }
6060
}
6161

62+
// NB: Distinguishes `@Selection` from `@Table`.
63+
public protocol _Selection: Table {}
64+
6265
extension Table {
6366
/// A select statement on the table with no constraints.
6467
///

Sources/StructuredQueriesCore/_Selection.swift

Lines changed: 0 additions & 17 deletions
This file was deleted.

Sources/StructuredQueriesMacros/Internal/DeclGroupSyntax.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,21 @@ extension DeclGroupSyntax {
1414
?? self.as(EnumDeclSyntax.self)?.name
1515
}
1616

17-
func hasMacroApplication(_ name: String) -> Bool {
17+
func macroApplication(for name: String) -> AttributeSyntax? {
1818
for attribute in attributes {
1919
switch attribute {
2020
case .attribute(let attr):
2121
if attr.attributeName.tokens(viewMode: .all).map({ $0.tokenKind }) == [.identifier(name)] {
22-
return true
22+
return attr
2323
}
2424
default:
2525
break
2626
}
2727
}
28-
return false
28+
return nil
29+
}
30+
31+
func hasMacroApplication(_ name: String) -> Bool {
32+
macroApplication(for: name) != nil
2933
}
3034
}

Sources/StructuredQueriesMacros/Plugin.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ struct StructuredQueriesPlugin: CompilerPlugin {
88
ColumnMacro.self,
99
ColumnsMacro.self,
1010
EphemeralMacro.self,
11-
SelectionMacro.self,
1211
SQLMacro.self,
1312
TableMacro.self,
1413
]

0 commit comments

Comments
 (0)