Skip to content

Commit c73a568

Browse files
MaxDesiatovfurby-tm
authored andcommitted
Add HashEncoder and QueryEngineTests (swiftlang#7435)
Depends on swiftlang#7347. Previously, `QueryEngine` couldn't cache anything due to a missing hashing implementation that could be consistent across SwiftPM relaunches. Here `HashEncoder` is implemented on top `Codable`. While it probably has certain performance overhead when compared to an implementation with macros, it should be good enough for prototyping. New `QueryEngine` now works for trivial computations, as verified by newly added `QueryEngineTests`.
1 parent b009650 commit c73a568

13 files changed

+692
-105
lines changed

Package.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ let package = Package(
359359
/** Support for building using Xcode's build system */
360360
name: "XCBuildSupport",
361361
dependencies: ["DriverSupport", "SPMBuildCore", "PackageGraph"],
362-
exclude: ["CMakeLists.txt", "CODEOWNERS"]
362+
exclude: ["CMakeLists.txt"]
363363
),
364364
.target(
365365
/** High level functionality */
@@ -473,6 +473,9 @@ let package = Package(
473473
dependencies: [
474474
"Basics",
475475
.product(name: "Crypto", package: "swift-crypto"),
476+
],
477+
swiftSettings: [
478+
.enableExperimentalFeature("StrictConcurrency=complete"),
476479
]
477480
),
478481

@@ -533,7 +536,7 @@ let package = Package(
533536
"Commands",
534537
"SwiftSDKCommand",
535538
"PackageCollectionsCommand",
536-
"PackageRegistryCommand"
539+
"PackageRegistryCommand",
537540
],
538541
linkerSettings: swiftpmLinkSettings
539542
),
@@ -672,6 +675,10 @@ let package = Package(
672675
name: "PackageSigningTests",
673676
dependencies: ["SPMTestSupport", "PackageSigning"]
674677
),
678+
.testTarget(
679+
name: "QueryEngineTests",
680+
dependencies: ["QueryEngine", "SPMTestSupport"]
681+
),
675682
.testTarget(
676683
name: "SourceControlTests",
677684
dependencies: ["SourceControl", "SPMTestSupport"],

Sources/Basics/SQLite.swift

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,20 @@ import SPMSQLite3
1919
#endif
2020

2121
/// A minimal SQLite wrapper.
22-
public final class SQLite {
22+
package final class SQLite {
2323
/// The location of the database.
24-
public let location: Location
24+
package let location: Location
2525

2626
/// The configuration for the database.
27-
public let configuration: Configuration
27+
package let configuration: Configuration
2828

2929
/// Pointer to the database.
3030
let db: OpaquePointer
3131

3232
/// Create or open the database at the given path.
3333
///
3434
/// The database is opened in serialized mode.
35-
public init(location: Location, configuration: Configuration = Configuration()) throws {
35+
package init(location: Location, configuration: Configuration = Configuration()) throws {
3636
self.location = location
3737
self.configuration = configuration
3838

@@ -64,19 +64,19 @@ public final class SQLite {
6464
}
6565

6666
@available(*, deprecated, message: "use init(location:configuration) instead")
67-
public convenience init(dbPath: AbsolutePath) throws {
67+
package convenience init(dbPath: AbsolutePath) throws {
6868
try self.init(location: .path(dbPath))
6969
}
7070

7171
/// Prepare the given query.
72-
public func prepare(query: String) throws -> PreparedStatement {
72+
package func prepare(query: String) throws -> PreparedStatement {
7373
try PreparedStatement(db: self.db, query: query)
7474
}
7575

7676
/// Directly execute the given query.
7777
///
7878
/// Note: Use withCString for string arguments.
79-
public func exec(query queryString: String, args: [CVarArg] = [], _ callback: SQLiteExecCallback? = nil) throws {
79+
package func exec(query queryString: String, args: [CVarArg] = [], _ callback: SQLiteExecCallback? = nil) throws {
8080
let query = withVaList(args) { ptr in
8181
sqlite3_vmprintf(queryString, ptr)
8282
}
@@ -96,27 +96,27 @@ public final class SQLite {
9696
}
9797
}
9898

99-
public func close() throws {
99+
package func close() throws {
100100
try Self.checkError { sqlite3_close(db) }
101101
}
102102

103-
public typealias SQLiteExecCallback = ([Column]) -> Void
103+
package typealias SQLiteExecCallback = ([Column]) -> Void
104104

105-
public struct Configuration {
106-
public var busyTimeoutMilliseconds: Int32
107-
public var maxSizeInBytes: Int?
105+
package struct Configuration {
106+
package var busyTimeoutMilliseconds: Int32
107+
package var maxSizeInBytes: Int?
108108

109109
// https://www.sqlite.org/pgszchng2016.html
110110
private let defaultPageSizeInBytes = 1024
111111

112-
public init() {
112+
package init() {
113113
self.busyTimeoutMilliseconds = 5000
114114
self.maxSizeInBytes = .none
115115
}
116116

117117
// FIXME: deprecated 12/2020, remove once clients migrated over
118118
@available(*, deprecated, message: "use busyTimeout instead")
119-
public var busyTimeoutSeconds: Int32 {
119+
package var busyTimeoutSeconds: Int32 {
120120
get {
121121
self._busyTimeoutSeconds
122122
} set {
@@ -133,7 +133,7 @@ public final class SQLite {
133133
}
134134
}
135135

136-
public var maxSizeInMegabytes: Int? {
136+
package var maxSizeInMegabytes: Int? {
137137
get {
138138
self.maxSizeInBytes.map { $0 / (1024 * 1024) }
139139
}
@@ -142,12 +142,12 @@ public final class SQLite {
142142
}
143143
}
144144

145-
public var maxPageCount: Int? {
145+
package var maxPageCount: Int? {
146146
self.maxSizeInBytes.map { $0 / self.defaultPageSizeInBytes }
147147
}
148148
}
149149

150-
public enum Location {
150+
package enum Location: Sendable {
151151
case path(AbsolutePath)
152152
case memory
153153
case temporary
@@ -165,59 +165,59 @@ public final class SQLite {
165165
}
166166

167167
/// Represents an sqlite value.
168-
public enum SQLiteValue {
168+
package enum SQLiteValue {
169169
case null
170170
case string(String)
171171
case int(Int)
172172
case blob(Data)
173173
}
174174

175175
/// Represents a row returned by called step() on a prepared statement.
176-
public struct Row {
176+
package struct Row {
177177
/// The pointer to the prepared statement.
178178
let stmt: OpaquePointer
179179

180180
/// Get integer at the given column index.
181-
public func int(at index: Int32) -> Int {
181+
package func int(at index: Int32) -> Int {
182182
Int(sqlite3_column_int64(self.stmt, index))
183183
}
184184

185185
/// Get blob data at the given column index.
186-
public func blob(at index: Int32) -> Data {
186+
package func blob(at index: Int32) -> Data {
187187
let bytes = sqlite3_column_blob(stmt, index)!
188188
let count = sqlite3_column_bytes(stmt, index)
189189
return Data(bytes: bytes, count: Int(count))
190190
}
191191

192192
/// Get string at the given column index.
193-
public func string(at index: Int32) -> String {
193+
package func string(at index: Int32) -> String {
194194
String(cString: sqlite3_column_text(self.stmt, index))
195195
}
196196
}
197197

198-
public struct Column {
199-
public var name: String
200-
public var value: String
198+
package struct Column {
199+
package var name: String
200+
package var value: String
201201
}
202202

203203
/// Represents a prepared statement.
204-
public struct PreparedStatement {
204+
package struct PreparedStatement {
205205
typealias sqlite3_destructor_type = @convention(c) (UnsafeMutableRawPointer?) -> Void
206206
static let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self)
207207
static let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
208208

209209
/// The pointer to the prepared statement.
210210
let stmt: OpaquePointer
211211

212-
public init(db: OpaquePointer, query: String) throws {
212+
package init(db: OpaquePointer, query: String) throws {
213213
var stmt: OpaquePointer?
214214
try SQLite.checkError { sqlite3_prepare_v2(db, query, -1, &stmt, nil) }
215215
self.stmt = stmt!
216216
}
217217

218218
/// Evaluate the prepared statement.
219219
@discardableResult
220-
public func step() throws -> Row? {
220+
package func step() throws -> Row? {
221221
let result = sqlite3_step(stmt)
222222

223223
switch result {
@@ -231,7 +231,7 @@ public final class SQLite {
231231
}
232232

233233
/// Bind the given arguments to the statement.
234-
public func bind(_ arguments: [SQLiteValue]) throws {
234+
package func bind(_ arguments: [SQLiteValue]) throws {
235235
for (idx, argument) in arguments.enumerated() {
236236
let idx = Int32(idx) + 1
237237
switch argument {
@@ -258,17 +258,17 @@ public final class SQLite {
258258
}
259259

260260
/// Reset the prepared statement.
261-
public func reset() throws {
261+
package func reset() throws {
262262
try SQLite.checkError { sqlite3_reset(stmt) }
263263
}
264264

265265
/// Clear bindings from the prepared statement.
266-
public func clearBindings() throws {
266+
package func clearBindings() throws {
267267
try SQLite.checkError { sqlite3_clear_bindings(stmt) }
268268
}
269269

270270
/// Finalize the statement and free up resources.
271-
public func finalize() throws {
271+
package func finalize() throws {
272272
try SQLite.checkError { sqlite3_finalize(stmt) }
273273
}
274274
}
@@ -296,7 +296,7 @@ public final class SQLite {
296296
}
297297
}
298298

299-
public enum Errors: Error {
299+
package enum Errors: Error {
300300
case databaseFull
301301
}
302302
}

Sources/Basics/SQLiteBackedCache.swift

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import class TSCBasic.InMemoryFileSystem
1717
import var TSCBasic.localFileSystem
1818

1919
/// SQLite backed persistent cache.
20-
public final class SQLiteBackedCache<Value: Codable>: Closable {
21-
public typealias Key = String
20+
package final class SQLiteBackedCache<Value: Codable>: Closable {
21+
package typealias Key = String
2222

23-
public let tableName: String
24-
public let fileSystem: FileSystem
25-
public let location: SQLite.Location
26-
public let configuration: SQLiteBackedCacheConfiguration
23+
package let tableName: String
24+
package let fileSystem: FileSystem
25+
package let location: SQLite.Location
26+
package let configuration: SQLiteBackedCacheConfiguration
2727

2828
private var state = State.idle
2929
private let stateLock = NSLock()
@@ -37,7 +37,7 @@ public final class SQLiteBackedCache<Value: Codable>: Closable {
3737
/// - tableName: The SQLite table name. Must follow SQLite naming rules (e.g., no spaces).
3838
/// - location: SQLite.Location
3939
/// - configuration: Optional. Configuration for the cache.
40-
public init(tableName: String, location: SQLite.Location, configuration: SQLiteBackedCacheConfiguration = .init()) {
40+
package init(tableName: String, location: SQLite.Location, configuration: SQLiteBackedCacheConfiguration = .init()) {
4141
self.tableName = tableName
4242
self.location = location
4343
switch self.location {
@@ -57,7 +57,7 @@ public final class SQLiteBackedCache<Value: Codable>: Closable {
5757
/// - tableName: The SQLite table name. Must follow SQLite naming rules (e.g., no spaces).
5858
/// - path: The path of the SQLite database.
5959
/// - configuration: Optional. Configuration for the cache.
60-
public convenience init(
60+
package convenience init(
6161
tableName: String,
6262
path: AbsolutePath,
6363
configuration: SQLiteBackedCacheConfiguration = .init()
@@ -75,7 +75,7 @@ public final class SQLiteBackedCache<Value: Codable>: Closable {
7575
}
7676
}
7777

78-
public func close() throws {
78+
package func close() throws {
7979
try self.withStateLock {
8080
if case .connected(let db) = self.state {
8181
try db.close()
@@ -122,7 +122,7 @@ public final class SQLiteBackedCache<Value: Codable>: Closable {
122122
}
123123
}
124124

125-
public func put(
125+
package func put(
126126
blobKey key: some Sequence<UInt8>,
127127
value: Value,
128128
replace: Bool = false,
@@ -131,7 +131,7 @@ public final class SQLiteBackedCache<Value: Codable>: Closable {
131131
try self.put(rawKey: .blob(Data(key)), value: value, observabilityScope: observabilityScope)
132132
}
133133

134-
public func put(
134+
package func put(
135135
key: Key,
136136
value: Value,
137137
replace: Bool = false,
@@ -140,7 +140,7 @@ public final class SQLiteBackedCache<Value: Codable>: Closable {
140140
try self.put(rawKey: .string(key), value: value, replace: replace, observabilityScope: observabilityScope)
141141
}
142142

143-
public func get(key: Key) throws -> Value? {
143+
package func get(key: Key) throws -> Value? {
144144
let query = "SELECT value FROM \(self.tableName) WHERE key = ? LIMIT 1;"
145145
return try self.executeStatement(query) { statement -> Value? in
146146
try statement.bind([.string(key)])
@@ -151,7 +151,7 @@ public final class SQLiteBackedCache<Value: Codable>: Closable {
151151
}
152152
}
153153

154-
public func get(blobKey key: some Sequence<UInt8>) throws -> Value? {
154+
package func get(blobKey key: some Sequence<UInt8>) throws -> Value? {
155155
let query = "SELECT value FROM \(self.tableName) WHERE key = ? LIMIT 1;"
156156
return try self.executeStatement(query) { statement -> Value? in
157157
try statement.bind([.blob(Data(key))])
@@ -162,7 +162,7 @@ public final class SQLiteBackedCache<Value: Codable>: Closable {
162162
}
163163
}
164164

165-
public func remove(key: Key) throws {
165+
package func remove(key: Key) throws {
166166
let query = "DELETE FROM \(self.tableName) WHERE key = ?;"
167167
try self.executeStatement(query) { statement in
168168
try statement.bind([.string(key)])
@@ -254,20 +254,20 @@ public final class SQLiteBackedCache<Value: Codable>: Closable {
254254
}
255255
}
256256

257-
public struct SQLiteBackedCacheConfiguration {
258-
public var truncateWhenFull: Bool
257+
package struct SQLiteBackedCacheConfiguration {
258+
package var truncateWhenFull: Bool
259259

260260
fileprivate var underlying: SQLite.Configuration
261261

262-
public init() {
262+
package init() {
263263
self.underlying = .init()
264264
self.truncateWhenFull = true
265265
self.maxSizeInMegabytes = 100
266266
// see https://www.sqlite.org/c3ref/busy_timeout.html
267267
self.busyTimeoutMilliseconds = 1000
268268
}
269269

270-
public var maxSizeInMegabytes: Int? {
270+
package var maxSizeInMegabytes: Int? {
271271
get {
272272
self.underlying.maxSizeInMegabytes
273273
}
@@ -276,7 +276,7 @@ public struct SQLiteBackedCacheConfiguration {
276276
}
277277
}
278278

279-
public var maxSizeInBytes: Int? {
279+
package var maxSizeInBytes: Int? {
280280
get {
281281
self.underlying.maxSizeInBytes
282282
}
@@ -285,7 +285,7 @@ public struct SQLiteBackedCacheConfiguration {
285285
}
286286
}
287287

288-
public var busyTimeoutMilliseconds: Int32 {
288+
package var busyTimeoutMilliseconds: Int32 {
289289
get {
290290
self.underlying.busyTimeoutMilliseconds
291291
}

0 commit comments

Comments
 (0)