Skip to content

Commit af4db5b

Browse files
committed
wip
1 parent d2567d7 commit af4db5b

File tree

4 files changed

+74
-3
lines changed

4 files changed

+74
-3
lines changed

Sources/StructuredQueriesSQLiteCore/DatabaseFunction.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
///
33
/// Don't conform to this protocol directly. Instead, use the `@DatabaseFunction` macro to generate
44
/// a conformance.
5-
public protocol DatabaseFunction {
5+
public protocol DatabaseFunction<Input, Output> {
6+
associatedtype Input
7+
associatedtype Output
8+
69
/// The name of the function.
710
var name: String { get }
811

@@ -14,11 +17,22 @@ public protocol DatabaseFunction {
1417
var isDeterministic: Bool { get }
1518
}
1619

17-
public protocol ScalarDatabaseFunction: DatabaseFunction {
20+
public protocol ScalarDatabaseFunction<Input, Output>: DatabaseFunction {
1821
/// The function body. Transforms an array of bindings handed to the function into a binding
1922
/// returned to the query.
2023
///
2124
/// - Parameter arguments: Arguments passed to the database function.
2225
/// - Returns: A value returned from the database function.
2326
func invoke(_ arguments: [QueryBinding]) -> QueryBinding
2427
}
28+
29+
extension ScalarDatabaseFunction {
30+
public func callAsFunction<each T: QueryExpression>(
31+
_ input: repeat each T
32+
) -> some QueryExpression<Output>
33+
where Input == (repeat (each T).QueryValue) {
34+
SQLQueryExpression(
35+
"\(quote: name)(\(Array(repeat each input).joined(separator: ", ")))"
36+
)
37+
}
38+
}

Sources/StructuredQueriesSQLiteMacros/DatabaseFunctionMacro.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,19 @@ extension DatabaseFunctionMacro: PeerMacro {
125125
parameters.append("\(parameter.secondName ?? parameter.firstName)")
126126
argumentBindings.append("let n\(offset) = \(type)(queryBinding: arguments[\(offset)])")
127127
}
128+
var inputType = bodyArguments.joined(separator: ", ")
128129
let bodyReturnClause: String
130+
let outputType: TypeSyntax
129131
if let returnClause = signature.returnClause {
132+
outputType = returnClause.type.trimmed
130133
signature.returnClause?.type = returnClause.type.asQueryExpression()
131134
bodyReturnClause = " \(returnClause.trimmedDescription)"
132135
} else {
136+
outputType = "Void"
133137
bodyReturnClause = " -> Void"
134138
}
135139
let bodyType = """
136-
(\(bodyArguments.joined(separator: ", ")))\
140+
(\(inputType))\
137141
\(declaration.signature.effectSpecifiers?.trimmedDescription ?? "")\
138142
\(bodyReturnClause)
139143
"""
@@ -174,6 +178,7 @@ extension DatabaseFunctionMacro: PeerMacro {
174178
continue
175179
}
176180
}
181+
inputType = bodyArguments.count == 1 ? inputType : "(\(inputType))"
177182

178183
return [
179184
"""
@@ -184,6 +189,8 @@ extension DatabaseFunctionMacro: PeerMacro {
184189
"""
185190
\(attributes)\(access)struct \(functionTypeName): \
186191
StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
192+
public typealias Input = \(raw: inputType)
193+
public typealias Output = \(outputType)
187194
public let name = \(databaseFunctionName)
188195
public let argumentCount: Int? = \(raw: argumentCount)
189196
public let isDeterministic = \(raw: isDeterministic)

Tests/StructuredQueriesMacrosTests/DatabaseFunctionMacroTests.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ extension SnapshotTests {
2424
}
2525
2626
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
27+
public typealias Input = ()
28+
public typealias Output = Date
2729
public let name = "currentDate"
2830
public let argumentCount: Int? = 0
2931
public let isDeterministic = false
@@ -70,6 +72,8 @@ extension SnapshotTests {
7072
}
7173
7274
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
75+
public typealias Input = ()
76+
public typealias Output = Date
7377
public let name = "current_date"
7478
public let argumentCount: Int? = 0
7579
public let isDeterministic = false
@@ -116,6 +120,8 @@ extension SnapshotTests {
116120
}
117121
118122
struct __macro_local_8fortyTwofMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
123+
public typealias Input = ()
124+
public typealias Output = Int
119125
public let name = "fortyTwo"
120126
public let argumentCount: Int? = 0
121127
public let isDeterministic = true
@@ -162,6 +168,8 @@ extension SnapshotTests {
162168
}
163169
164170
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
171+
public typealias Input = String
172+
public typealias Output = Date?
165173
public let name = "currentDate"
166174
public let argumentCount: Int? = 1
167175
public let isDeterministic = false
@@ -208,6 +216,8 @@ extension SnapshotTests {
208216
}
209217
210218
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
219+
public typealias Input = String
220+
public typealias Output = Date?
211221
public let name = "currentDate"
212222
public let argumentCount: Int? = 1
213223
public let isDeterministic = false
@@ -254,6 +264,8 @@ extension SnapshotTests {
254264
}
255265
256266
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
267+
public typealias Input = String
268+
public typealias Output = Date?
257269
public let name = "currentDate"
258270
public let argumentCount: Int? = 1
259271
public let isDeterministic = false
@@ -300,6 +312,8 @@ extension SnapshotTests {
300312
}
301313
302314
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
315+
public typealias Input = String
316+
public typealias Output = Date?
303317
public let name = "currentDate"
304318
public let argumentCount: Int? = 1
305319
public let isDeterministic = false
@@ -346,6 +360,8 @@ extension SnapshotTests {
346360
}
347361
348362
struct __macro_local_6concatfMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
363+
public typealias Input = (String, String)
364+
public typealias Output = String
349365
public let name = "concat"
350366
public let argumentCount: Int? = 2
351367
public let isDeterministic = false
@@ -409,6 +425,8 @@ extension SnapshotTests {
409425
}
410426
411427
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
428+
public typealias Input = String?
429+
public typealias Output = Date?
412430
public let name = "currentDate"
413431
public let argumentCount: Int? = 1
414432
public let isDeterministic = false
@@ -455,6 +473,8 @@ extension SnapshotTests {
455473
}
456474
457475
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
476+
public typealias Input = ()
477+
public typealias Output = Date
458478
public let name = "currentDate"
459479
public let argumentCount: Int? = 0
460480
public let isDeterministic = false
@@ -505,6 +525,8 @@ extension SnapshotTests {
505525
}
506526
507527
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
528+
public typealias Input = ()
529+
public typealias Output = Date
508530
public let name = "currentDate"
509531
public let argumentCount: Int? = 0
510532
public let isDeterministic = false
@@ -555,6 +577,8 @@ extension SnapshotTests {
555577
}
556578
557579
public struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
580+
public typealias Input = ()
581+
public typealias Output = Date
558582
public let name = "currentDate"
559583
public let argumentCount: Int? = 0
560584
public let isDeterministic = false
@@ -601,6 +625,8 @@ extension SnapshotTests {
601625
}
602626
603627
struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
628+
public typealias Input = ()
629+
public typealias Output = Date
604630
public let name = "currentDate"
605631
public let argumentCount: Int? = 0
606632
public let isDeterministic = false
@@ -670,6 +696,8 @@ extension SnapshotTests {
670696
}
671697
672698
@available(*, unavailable) struct __macro_local_11currentDatefMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
699+
public typealias Input = ()
700+
public typealias Output = Date
673701
public let name = "currentDate"
674702
public let argumentCount: Int? = 0
675703
public let isDeterministic = false
@@ -716,6 +744,8 @@ extension SnapshotTests {
716744
}
717745
718746
public struct __macro_local_7defaultfMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
747+
public typealias Input = ()
748+
public typealias Output = Int
719749
public let name = "default"
720750
public let argumentCount: Int? = 0
721751
public let isDeterministic = false
@@ -779,6 +809,8 @@ extension SnapshotTests {
779809
}
780810
781811
public struct __macro_local_4voidfMu_: StructuredQueriesSQLiteCore.ScalarDatabaseFunction {
812+
public typealias Input = ()
813+
public typealias Output = <#QueryBindable#>
782814
public let name = "void"
783815
public let argumentCount: Int? = 0
784816
public let isDeterministic = false

Tests/StructuredQueriesTests/DatabaseFunctionTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,24 @@ extension SnapshotTests {
7676
}
7777
}
7878

79+
@Test func erasedConcat() {
80+
@Dependency(\.defaultDatabase) var database
81+
$concat.install(database.handle)
82+
assertQuery(
83+
Values($concat("foo", "bar"))
84+
) {
85+
"""
86+
SELECT "concat"('foo', 'bar')
87+
"""
88+
} results: {
89+
"""
90+
┌──────────┐
91+
"foobar"
92+
└──────────┘
93+
"""
94+
}
95+
}
96+
7997
@DatabaseFunction
8098
func throwing() throws -> String {
8199
struct Failure: LocalizedError {

0 commit comments

Comments
 (0)