Skip to content

Commit

Permalink
Leverage improvements in SQLKit and SQLiteNIO (#108)
Browse files Browse the repository at this point in the history
* Update package structure, bump Swift minimum to 5.8, require an SQLKit we actually need, update CI, fix ExistentialAny usage, fix readme, update docs and logo
* Sendable correctness, de-underscore the SQLite version type, add support for specifying JSON encoders and decoders, add support for new SQLKit functionality, default to singleton NIOThreadPool, modernize data encoder and decoder to handle data better and faster
* Add 100% doc comments coverage
* Use un-deprecated SQLBenchmarker API
* Update dep minimums
* Take advantage of further improvements in SQLiteNIO - SQLiteDatabase is Sendable, support queryLogLevel, don't do extra thread hops in withSession()
* Pedantically avoid API breakage with SQLiteDatabase.sql() and make it @inlinable, fix a Sendability warning, add a missing doc comment.
  • Loading branch information
gwynne authored May 14, 2024
1 parent e9fd69b commit 37c1a39
Show file tree
Hide file tree
Showing 18 changed files with 723 additions and 246 deletions.
9 changes: 8 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
* @0xTim @gwynne
* @gwynne
/.github/CONTRIBUTING.md @gwynne @0xTim
/.github/workflows/*.yml @gwynne @0xTim
/.github/workflows/test.yml @gwynne
/.spi.yml @gwynne @0xTim
/.gitignore @gwynne @0xTim
/LICENSE @gwynne @0xTim
/README.md @gwynne @0xTim
12 changes: 0 additions & 12 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
version: 2
enable-beta-ecosystems: true
updates:
- package-ecosystem: "github-actions"
directory: "/"
Expand All @@ -9,14 +8,3 @@ updates:
dependencies:
patterns:
- "*"
- package-ecosystem: "swift"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 6
allow:
- dependency-type: all
groups:
all-dependencies:
patterns:
- "*"
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ jobs:
# also serves as code coverage baseline update
unit-tests:
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
secrets: inherit

# Make sure downstream dependents still work
dependents-check:
if: ${{ !(github.event.pull_request.draft || false) }}
runs-on: ubuntu-latest
container: swift:5.9-jammy
container: swift:5.10-jammy
steps:
- name: Check out package
uses: actions/checkout@v4
Expand Down
39 changes: 26 additions & 13 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.7
// swift-tools-version:5.8
import PackageDescription

let package = Package(
Expand All @@ -13,21 +13,34 @@ let package = Package(
.library(name: "SQLiteKit", targets: ["SQLiteKit"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.62.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.65.0"),
.package(url: "https://github.com/vapor/sqlite-nio.git", from: "1.8.4"),
.package(url: "https://github.com/vapor/sql-kit.git", from: "3.28.0"),
.package(url: "https://github.com/vapor/sql-kit.git", from: "3.29.3"),
.package(url: "https://github.com/vapor/async-kit.git", from: "1.19.0"),
],
targets: [
.target(name: "SQLiteKit", dependencies: [
.product(name: "NIOFoundationCompat", package: "swift-nio"),
.product(name: "AsyncKit", package: "async-kit"),
.product(name: "SQLiteNIO", package: "sqlite-nio"),
.product(name: "SQLKit", package: "sql-kit"),
]),
.testTarget(name: "SQLiteKitTests", dependencies: [
.product(name: "SQLKitBenchmark", package: "sql-kit"),
.target(name: "SQLiteKit"),
]),
.target(
name: "SQLiteKit",
dependencies: [
.product(name: "NIOFoundationCompat", package: "swift-nio"),
.product(name: "AsyncKit", package: "async-kit"),
.product(name: "SQLiteNIO", package: "sqlite-nio"),
.product(name: "SQLKit", package: "sql-kit"),
],
swiftSettings: swiftSettings
),
.testTarget(
name: "SQLiteKitTests",
dependencies: [
.product(name: "SQLKitBenchmark", package: "sql-kit"),
.target(name: "SQLiteKit"),
],
swiftSettings: swiftSettings
),
]
)

var swiftSettings: [SwiftSetting] { [
.enableUpcomingFeature("ConciseMagicFile"),
.enableUpcomingFeature("ForwardTrailingClosures"),
] }
17 changes: 10 additions & 7 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
// swift-tools-version:5.9
import PackageDescription

let swiftSettings: [SwiftSetting] = [
.enableUpcomingFeature("ExistentialAny"),
.enableExperimentalFeature("StrictConcurrency=complete"),
]

let package = Package(
name: "sqlite-kit",
platforms: [
Expand All @@ -18,9 +13,9 @@ let package = Package(
.library(name: "SQLiteKit", targets: ["SQLiteKit"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-nio.git", from: "2.62.0"),
.package(url: "https://github.com/apple/swift-nio.git", from: "2.65.0"),
.package(url: "https://github.com/vapor/sqlite-nio.git", from: "1.8.4"),
.package(url: "https://github.com/vapor/sql-kit.git", from: "3.28.0"),
.package(url: "https://github.com/vapor/sql-kit.git", from: "3.29.3"),
.package(url: "https://github.com/vapor/async-kit.git", from: "1.19.0"),
],
targets: [
Expand All @@ -44,3 +39,11 @@ let package = Package(
),
]
)

var swiftSettings: [SwiftSetting] { [
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("ConciseMagicFile"),
.enableUpcomingFeature("ForwardTrailingClosures"),
.enableUpcomingFeature("DisableOutwardActorInference"),
.enableExperimentalFeature("StrictConcurrency=complete"),
] }
37 changes: 24 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/vapor/sqlite-kit/assets/1130717/2d99c0b9-35e5-4f04-bb6c-8d59ff6e78c6">
<source media="(prefers-color-scheme: light)" srcset="https://github.com/vapor/sqlite-kit/assets/1130717/cb36f94d-3ac3-4fba-b801-fe19eac7dbc2">
<img src="https://github.com/vapor/sqlite-kit/assets/1130717/cb36f94d-3ac3-4fba-b801-fe19eac7dbc2" height="96" alt="SQLiteKit">
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/vapor/sqlite-kit/assets/1130717/81e423ff-d8b7-49f7-8c40-0287b3f025cf">
<source media="(prefers-color-scheme: light)" srcset="https://github.com/vapor/sqlite-kit/assets/1130717/79147036-e050-4a87-be7c-68d6d2c40717">
<img src="https://github.com/vapor/sqlite-kit/assets/1130717/79147036-e050-4a87-be7c-68d6d2c40717" height="96" alt="SQLiteKit">
</picture>
<br>
<br>
<a href="https://docs.vapor.codes/4.0/"><img src="https://design.vapor.codes/images/readthedocs.svg" alt="Documentation"></a>
<a href="https://discord.gg/vapor"><img src="https://design.vapor.codes/images/discordchat.svg" alt="Team Chat"></a>
<a href="LICENSE"><img src="https://design.vapor.codes/images/mitlicense.svg" alt="MIT License"></a>
<a href="https://github.com/vapor/sqlite-kit/actions/workflows/test.yml"><img src="https://img.shields.io/github/actions/workflow/status/vapor/sqlite-kit/test.yml?event=push&style=plastic&logo=github&label=test&logoColor=%23ccc" alt="Continuous Integration"></a>
<a href="https://codecov.io/github/vapor/sqlite-kit"><img src="https://img.shields.io/codecov/c/github/vapor/sqlite-kit?style=plastic&logo=codecov&label=Codecov"></a>
<a href="https://swift.org"><img src="https://design.vapor.codes/images/swift57up.svg" alt="Swift 5.7+"></a>
<a href="https://www.swift.org/sswg/incubation-process.html"><img src="https://design.vapor.codes/images/sswg-graduated-white.svg" alt="SSWG Incubation Level: Graduated"></a>
<a href="https://codecov.io/github/vapor/sqlite-kit"><img src="https://img.shields.io/codecov/c/github/vapor/sqlite-kit?style=plastic&logo=codecov&label=codecov"></a>
<a href="https://swift.org"><img src="https://design.vapor.codes/images/swift58up.svg" alt="Swift 5.8+"></a>
<a href="https://www.swift.org/sswg/incubation-process.html"><img src="https://design.vapor.codes/images/sswg-graduated.svg" alt="SSWG Incubation Level: Graduated"></a>
</p>

<br>

SQLiteKit is a library providing an [SQLKit] driver for [SQLiteNIO].
SQLiteKit is an [SQLKit] driver for SQLite clients. It supports building and serializing SQLite-dialect SQL queries. SQLiteKit uses [SQLiteNIO] to connect and communicate with the database server asynchronously. [AsyncKit] is used to provide connection pooling.

> [!NOTE]
> The [FluentKit] driver for SQLite is provided by the [FluentSQLiteDriver] package.
[SQLKit]: https://github.com/vapor/sql-kit
[SQLiteNIO]: https://github.com/vapor/sqlite-nio
[AsyncKit]: https://github.com/vapor/async-kit

[SQLKit]: https://swiftpackageindex.com/vapor/sql-kit
[SQLiteNIO]: https://swiftpackageindex.com/vapor/sqlite-nio
[Fluent]: https://swiftpackageindex.com/vapor/fluent-kit
[FluentSQLiteDriver]: https://swiftpackageindex.com/vapor/fluent-sqlite-driver
### Usage

Use the SPM string to easily include the dependendency in your `Package.swift` file.

```swift
.package(url: "https://github.com/vapor/sqlite-kit.git", from: "4.0.0")
```

### Supported Platforms

SQLiteKit supports the following platforms:

- Ubuntu 20.04+
- macOS 10.15+
9 changes: 7 additions & 2 deletions Sources/SQLiteKit/Docs.docc/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ This package provides the "foundational" level of support for using [Fluent] wit

- Managing the underlying SQLite library ([SQLiteNIO]),
- Providing a two-way bridge between SQLiteNIO and SQLKit's generic data and metadata formats,
- Presenting an interface for establishing, managing, and interacting with database connections.
- Presenting an interface for establishing, managing, and interacting with database connections via [AsyncKit].

> Note: The FluentKit driver for SQLite is provided by the [FluentSQLiteDriver] package.
> Tip: The FluentKit driver for SQLite is provided by the [FluentSQLiteDriver] package.
## Version Support

This package uses [SQLiteNIO] for all underlying database interactions. The version of SQLite embedded by that package is always the one used.

[SQLKit]: https://swiftpackageindex.com/vapor/sql-kit
[SQLiteNIO]: https://swiftpackageindex.com/vapor/sqlite-nio
[Fluent]: https://swiftpackageindex.com/vapor/fluent-kit
[FluentSQLiteDriver]: https://swiftpackageindex.com/vapor/fluent-sqlite-driver
[AsyncKit]: https://swiftpackageindex.com/vapor/async-kit
27 changes: 13 additions & 14 deletions Sources/SQLiteKit/Docs.docc/images/vapor-sqlitekit-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions Sources/SQLiteKit/Docs.docc/theme-settings.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"theme": {
"aside": { "border-radius": "6px", "border-style": "double", "border-width": "3px" },
"aside": { "border-radius": "16px", "border-style": "double", "border-width": "3px" },
"border-radius": "0",
"button": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
"code": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
"color": {
"sqlite": "hsl(215, 45%, 58%)",
"documentation-intro-fill": "radial-gradient(circle at top, var(--color-sqlite) 30%, #000 100%)",
"documentation-intro-accent": "var(--color-sqlite)",
"sqlitekit": "hsl(215, 45%, 58%)",
"documentation-intro-fill": "radial-gradient(circle at top, var(--color-sqlitekit) 30%, #000 100%)",
"documentation-intro-accent": "var(--color-sqlitekit)",
"logo-base": { "dark": "#fff", "light": "#000" },
"logo-shape": { "dark": "#000", "light": "#fff" },
"fill": { "dark": "#000", "light": "#fff" }
Expand Down
11 changes: 0 additions & 11 deletions Sources/SQLiteKit/Exports.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
#if swift(>=5.8)

@_documentation(visibility: internal) @_exported import SQLKit
@_documentation(visibility: internal) @_exported import SQLiteNIO
@_documentation(visibility: internal) @_exported import AsyncKit
@_documentation(visibility: internal) @_exported import struct Logging.Logger

#else

@_exported import SQLKit
@_exported import SQLiteNIO
@_exported import AsyncKit
@_exported import struct Logging.Logger

#endif
44 changes: 32 additions & 12 deletions Sources/SQLiteKit/SQLiteConfiguration.swift
Original file line number Diff line number Diff line change
@@ -1,32 +1,52 @@
import struct Foundation.UUID

/// Describes a configuration for an SQLite database connection.
public struct SQLiteConfiguration: Sendable {
/// The possible storage types for an SQLite database.
public enum Storage: Sendable {
/// Stores the SQLite database in memory.
///
/// Uses a randomly generated identifier. See `memory(identifier:)`.
/// Specify an SQLite database stored in memory, using a randomly generated identifier.
///
/// See ``memory(identifier:)``.
public static var memory: Self {
.memory(identifier: UUID().uuidString)
}

/// Stores the SQLite database in memory.
/// - parameters:
/// - identifier: Uniquely identifies the in-memory storage.
/// Connections using the same identifier share data.
/// Specify an SQLite database stored in memory, using a given identifier string.
///
/// An in-memory database persists only until the last connection to it is closed. If a new connection is
/// opened after that point, even using the same identifier, a new, empty database is created.
///
/// - Parameter identifier: Uniquely identifies the in-memory storage. Multiple connections may use this
/// identifier to connect to the same in-memory storage for the duration of its lifetime. The identifer
/// has no predefined format or restrictions on its content.
case memory(identifier: String)

/// Uses the SQLite database file at the specified path.
/// Specify an SQLite database stored in a file at the specified path.
///
/// Non-absolute paths will check the current working directory.
/// If a relative path is specified, it is interpreted relative to the current working directory of the
/// current process (e.g. `NIOFileSystem.shared.currentWorkingDirectory`). It is recommended to always use
/// absolute paths whenever possible.
///
/// - Parameter path: The filesystem path at which to store the database.
case file(path: String)
}


/// The storage type for the database.
///
/// See ``Storage-swift.enum`` for the available storage types.
public var storage: Storage

/// If `true`, foreign keys will be enabled automatically on new connections.
/// When `true`, foreign key support is automatically enabled on all connections using this configuration.
///
/// Internally issues a `PRAGMA foreign_keys = ON` query when enabled.
public var enableForeignKeys: Bool

/// Creates a new `SQLiteConfiguration`.
/// Create a new ``SQLiteConfiguration``.
///
/// - Parameters:
/// - storage: The storage type to use for the database. See ``Storage-swift.enum``.
/// - enableForeignKeys: Whether to enable foreign key support by default for all connections.
/// Defaults to `true`.
public init(storage: Storage, enableForeignKeys: Bool = true) {
self.storage = storage
self.enableForeignKeys = enableForeignKeys
Expand Down
Loading

0 comments on commit 37c1a39

Please sign in to comment.