Skip to content

Commit c078249

Browse files
authored
@DatabaseFunction: Custom SQLite Functions (#151)
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip
1 parent 6f8bd35 commit c078249

38 files changed

+1587
-75
lines changed

.spi.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ builder:
44
- documentation_targets:
55
- StructuredQueriesCore
66
- StructuredQueries
7+
- StructuredQueriesSQLiteCore
8+
- StructuredQueriesSQLite
79
custom_documentation_parameters:
810
- '--enable-experimental-overloaded-symbol-presentation'
911
# - '--enable-experimental-combined-documentation'

Package.swift

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ let package = Package(
2121
targets: ["StructuredQueriesCore"]
2222
),
2323
.library(
24-
name: "StructuredQueriesTestSupport",
25-
targets: ["StructuredQueriesTestSupport"]
24+
name: "StructuredQueriesSQLite",
25+
targets: ["StructuredQueriesSQLite"]
2626
),
2727
.library(
28-
name: "_StructuredQueriesSQLite",
29-
targets: ["StructuredQueriesSQLite"]
28+
name: "StructuredQueriesSQLiteCore",
29+
targets: ["StructuredQueriesSQLiteCore"]
30+
),
31+
.library(
32+
name: "StructuredQueriesTestSupport",
33+
targets: ["StructuredQueriesTestSupport"]
3034
),
3135
],
3236
traits: [
@@ -46,6 +50,13 @@ let package = Package(
4650
.package(url: "https://github.com/swiftlang/swift-syntax", "600.0.0"..<"602.0.0"),
4751
],
4852
targets: [
53+
.target(
54+
name: "StructuredQueries",
55+
dependencies: [
56+
"StructuredQueriesCore",
57+
"StructuredQueriesMacros",
58+
]
59+
),
4960
.target(
5061
name: "StructuredQueriesCore",
5162
dependencies: [
@@ -58,13 +69,6 @@ let package = Package(
5869
],
5970
exclude: ["Symbolic Links/README.md"]
6071
),
61-
.target(
62-
name: "StructuredQueries",
63-
dependencies: [
64-
"StructuredQueriesCore",
65-
"StructuredQueriesMacros",
66-
]
67-
),
6872
.macro(
6973
name: "StructuredQueriesMacros",
7074
dependencies: [
@@ -73,12 +77,30 @@ let package = Package(
7377
],
7478
exclude: ["Symbolic Links/README.md"]
7579
),
80+
7681
.target(
7782
name: "StructuredQueriesSQLite",
7883
dependencies: [
79-
"StructuredQueries"
84+
"StructuredQueries",
85+
"StructuredQueriesSQLiteCore",
86+
"StructuredQueriesSQLiteMacros",
87+
]
88+
),
89+
.target(
90+
name: "StructuredQueriesSQLiteCore",
91+
dependencies: [
92+
"StructuredQueriesCore",
93+
.product(name: "IssueReporting", package: "xctest-dynamic-overlay")
94+
]
95+
),
96+
.macro(
97+
name: "StructuredQueriesSQLiteMacros",
98+
dependencies: [
99+
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
100+
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
80101
]
81102
),
103+
82104
.target(
83105
name: "StructuredQueriesTestSupport",
84106
dependencies: [
@@ -90,8 +112,8 @@ let package = Package(
90112
.testTarget(
91113
name: "StructuredQueriesMacrosTests",
92114
dependencies: [
93-
"StructuredQueries",
94115
"StructuredQueriesMacros",
116+
"StructuredQueriesSQLiteMacros",
95117
.product(name: "IssueReporting", package: "xctest-dynamic-overlay"),
96118
.product(name: "MacroTesting", package: "swift-macro-testing"),
97119
]
@@ -102,11 +124,19 @@ let package = Package(
102124
"StructuredQueries",
103125
"StructuredQueriesSQLite",
104126
"StructuredQueriesTestSupport",
127+
"_StructuredQueriesSQLite",
105128
.product(name: "CustomDump", package: "swift-custom-dump"),
106129
.product(name: "Dependencies", package: "swift-dependencies"),
107130
.product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"),
108131
]
109132
),
133+
134+
.target(
135+
name: "_StructuredQueriesSQLite",
136+
dependencies: [
137+
"StructuredQueriesSQLite"
138+
]
139+
),
110140
],
111141
swiftLanguageModes: [.v6]
112142
)
@@ -128,14 +158,14 @@ for index in package.targets.indices {
128158
#if !canImport(Darwin)
129159
package.targets.append(
130160
.systemLibrary(
131-
name: "StructuredQueriesSQLite3",
161+
name: "_StructuredQueriesSQLite3",
132162
providers: [.apt(["libsqlite3-dev"])]
133163
)
134164
)
135165

136166
for index in package.targets.indices {
137-
if package.targets[index].name == "StructuredQueriesSQLite" {
138-
package.targets[index].dependencies.append("StructuredQueriesSQLite3")
167+
if package.targets[index].name == "_StructuredQueriesSQLite" {
168+
package.targets[index].dependencies.append("_StructuredQueriesSQLite3")
139169
}
140170
}
141171
#endif

[email protected]

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,17 @@ let package = Package(
2525
targets: ["StructuredQueriesTestSupport"]
2626
),
2727
.library(
28-
name: "_StructuredQueriesSQLite",
28+
name: "StructuredQueriesSQLite",
2929
targets: ["StructuredQueriesSQLite"]
3030
),
31+
.library(
32+
name: "StructuredQueriesSQLiteCore",
33+
targets: ["StructuredQueriesSQLiteCore"]
34+
),
35+
.library(
36+
name: "StructuredQueriesTestSupport",
37+
targets: ["StructuredQueriesTestSupport"]
38+
),
3139
],
3240
dependencies: [
3341
.package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"),
@@ -38,20 +46,20 @@ let package = Package(
3846
.package(url: "https://github.com/swiftlang/swift-syntax", "600.0.0"..<"602.0.0"),
3947
],
4048
targets: [
41-
.target(
42-
name: "StructuredQueriesCore",
43-
dependencies: [
44-
.product(name: "IssueReporting", package: "xctest-dynamic-overlay")
45-
],
46-
exclude: ["Symbolic Links/README.md"]
47-
),
4849
.target(
4950
name: "StructuredQueries",
5051
dependencies: [
5152
"StructuredQueriesCore",
5253
"StructuredQueriesMacros",
5354
]
5455
),
56+
.target(
57+
name: "StructuredQueriesCore",
58+
dependencies: [
59+
.product(name: "IssueReporting", package: "xctest-dynamic-overlay")
60+
],
61+
exclude: ["Symbolic Links/README.md"]
62+
),
5563
.macro(
5664
name: "StructuredQueriesMacros",
5765
dependencies: [
@@ -60,12 +68,30 @@ let package = Package(
6068
],
6169
exclude: ["Symbolic Links/README.md"]
6270
),
71+
6372
.target(
6473
name: "StructuredQueriesSQLite",
6574
dependencies: [
66-
"StructuredQueries"
75+
"StructuredQueries",
76+
"StructuredQueriesSQLiteCore",
77+
"StructuredQueriesSQLiteMacros",
78+
]
79+
),
80+
.target(
81+
name: "StructuredQueriesSQLiteCore",
82+
dependencies: [
83+
"StructuredQueriesCore",
84+
.product(name: "IssueReporting", package: "xctest-dynamic-overlay")
85+
]
86+
),
87+
.macro(
88+
name: "StructuredQueriesSQLiteMacros",
89+
dependencies: [
90+
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
91+
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
6792
]
6893
),
94+
6995
.target(
7096
name: "StructuredQueriesTestSupport",
7197
dependencies: [
@@ -74,11 +100,12 @@ let package = Package(
74100
.product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"),
75101
]
76102
),
103+
77104
.testTarget(
78105
name: "StructuredQueriesMacrosTests",
79106
dependencies: [
80-
"StructuredQueries",
81107
"StructuredQueriesMacros",
108+
"StructuredQueriesSQLiteMacros",
82109
.product(name: "IssueReporting", package: "xctest-dynamic-overlay"),
83110
.product(name: "MacroTesting", package: "swift-macro-testing"),
84111
]
@@ -87,13 +114,20 @@ let package = Package(
87114
name: "StructuredQueriesTests",
88115
dependencies: [
89116
"StructuredQueries",
90-
"StructuredQueriesSQLite",
91117
"StructuredQueriesTestSupport",
118+
"_StructuredQueriesSQLite",
92119
.product(name: "CustomDump", package: "swift-custom-dump"),
93120
.product(name: "Dependencies", package: "swift-dependencies"),
94121
.product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"),
95122
]
96123
),
124+
125+
.target(
126+
name: "_StructuredQueriesSQLite",
127+
dependencies: [
128+
"StructuredQueriesSQLite"
129+
]
130+
),
97131
],
98132
swiftLanguageModes: [.v6]
99133
)
@@ -115,14 +149,14 @@ for index in package.targets.indices {
115149
#if !os(Darwin)
116150
package.targets.append(
117151
.systemLibrary(
118-
name: "StructuredQueriesSQLite3",
152+
name: "_StructuredQueriesSQLite3",
119153
providers: [.apt(["libsqlite3-dev"])]
120154
)
121155
)
122156

123157
for index in package.targets.indices {
124-
if package.targets[index].name == "StructuredQueriesSQLite" {
125-
package.targets[index].dependencies.append("StructuredQueriesSQLite3")
158+
if package.targets[index].name == "_StructuredQueriesSQLite" {
159+
package.targets[index].dependencies.append("_StructuredQueriesSQLite3")
126160
}
127161
}
128162
#endif

Sources/StructuredQueriesCore/Optional.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ extension Optional: QueryBindable where Wrapped: QueryBindable {
2727
public var queryBinding: QueryBinding {
2828
self?.queryBinding ?? .null
2929
}
30+
31+
public init?(queryBinding: QueryBinding) {
32+
self = Wrapped(queryBinding: queryBinding)
33+
}
3034
}
3135

3236
extension Optional: QueryDecodable where Wrapped: QueryDecodable {

Sources/StructuredQueriesCore/QueryBindable.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,26 @@ public protocol QueryBindable: QueryRepresentable, QueryExpression where QueryVa
99

1010
/// A value that can be bound to a parameter of a SQL statement.
1111
var queryBinding: QueryBinding { get }
12+
13+
/// Initializes a bindable type from a binding.
14+
init?(queryBinding: QueryBinding)
1215
}
1316

1417
extension QueryBindable {
1518
public var queryFragment: QueryFragment { "\(queryBinding)" }
19+
20+
public init?(queryBinding: QueryBinding) {
21+
guard let queryValue = QueryValue(queryBinding: queryBinding) else { return nil }
22+
self.init(queryBinding: queryValue.queryBinding)
23+
}
1624
}
1725

1826
extension [UInt8]: QueryBindable, QueryExpression {
1927
public var queryBinding: QueryBinding { .blob(self) }
28+
public init?(queryBinding: QueryBinding) {
29+
guard case .blob(let value) = queryBinding else { return nil }
30+
self = value
31+
}
2032
}
2133

2234
extension Bool: QueryBindable {
@@ -25,10 +37,18 @@ extension Bool: QueryBindable {
2537

2638
extension Double: QueryBindable {
2739
public var queryBinding: QueryBinding { .double(self) }
40+
public init?(queryBinding: QueryBinding) {
41+
guard case .double(let value) = queryBinding else { return nil }
42+
self = value
43+
}
2844
}
2945

3046
extension Date: QueryBindable {
3147
public var queryBinding: QueryBinding { .date(self) }
48+
public init?(queryBinding: QueryBinding) {
49+
guard case .date(let value) = queryBinding else { return nil }
50+
self = value
51+
}
3252
}
3353

3454
extension Float: QueryBindable {
@@ -53,10 +73,18 @@ extension Int32: QueryBindable {
5373

5474
extension Int64: QueryBindable {
5575
public var queryBinding: QueryBinding { .int(self) }
76+
public init?(queryBinding: QueryBinding) {
77+
guard case .int(let value) = queryBinding else { return nil }
78+
self = value
79+
}
5680
}
5781

5882
extension String: QueryBindable {
5983
public var queryBinding: QueryBinding { .text(self) }
84+
public init?(queryBinding: QueryBinding) {
85+
guard case let .text(value) = queryBinding else { return nil }
86+
self = value
87+
}
6088
}
6189

6290
extension UInt8: QueryBindable {
@@ -83,6 +111,10 @@ extension UInt64: QueryBindable {
83111

84112
extension UUID: QueryBindable {
85113
public var queryBinding: QueryBinding { .uuid(self) }
114+
public init?(queryBinding: QueryBinding) {
115+
guard case .uuid(let value) = queryBinding else { return nil }
116+
self = value
117+
}
86118
}
87119

88120
extension DefaultStringInterpolation {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# ``StructuredQueriesSQLite``
2+
3+
Core SQLite extensions to StructuredQueries.
4+
5+
## Overview
6+
7+
The core functionality of this library is defined in
8+
[`StructuredQueriesSQLiteCore`](<doc:/StructuredQueriesSQLiteCore>), which this module automatically
9+
exports.
10+
11+
This module also contains all of the macros that support the core functionality of the library.
12+
13+
See [`StructuredQueriesSQLiteCore`](<doc:/StructuredQueriesSQLiteCore>) for general library usage.
14+
15+
## Topics
16+
17+
### Macros
18+
19+
- ``DatabaseFunction(_:isDeterministic:)``
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@_exported import StructuredQueries
2+
@_exported import StructuredQueriesSQLiteCore
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import StructuredQueriesSQLiteCore
2+
3+
/// Defines and implements a conformance to the ``/StructuredQueriesSQLiteCore/DatabaseFunction``
4+
/// protocol.
5+
///
6+
/// - Parameters
7+
/// - name: The function's name. Defaults to the name of the function the macro is applied to.
8+
/// - isDeterministic: Whether or not the function is deterministic (or "pure" or "referentially
9+
/// transparent"), _i.e._ given an input it will always return the same output.
10+
@attached(peer, names: overloaded, prefixed(`$`))
11+
public macro DatabaseFunction(
12+
_ name: String = "",
13+
isDeterministic: Bool = false
14+
) =
15+
#externalMacro(
16+
module: "StructuredQueriesSQLiteMacros",
17+
type: "DatabaseFunctionMacro"
18+
)

0 commit comments

Comments
 (0)