I'd like to pitch my OracleNIO library to the SSWG incubation process. It provides a database driver for interacting with Oracle databases starting with version 12.1.
Motivation
Oracle databases are widely used, especially in enterprise. People (myself included) have asked about the existence of an Oracle driver in the past (Vapor Discord, Swift Forums Thread, StackOverflow, Apple Developer Forums, ...).
Previously it was only possible to integrate with Oracle databases by wrapping a C library, which required a few system dependencies such as Oracle Call Interface (OCI) and others. The setup and usage was not ideal and error prone.
I believe that it is a great addition to the SSWG projects and would make Swift a viable choice for projects integrating with Oracle databases.
Proposed solution
During the last year, I've created a standalone Swift driver based on SwiftNIO. This is the first standalone driver in any language not developed directly by Oracle, most other drivers require OCI or ODPI-C. Due to that, OracleNIO does not require any system dependencies and works out of the box, like PostgresNIO and others.
The protocol implementation is based on python-oracledb (thin mode), node-oracledb (thin mode), and contact with Anthony Tuininga, Christopher Jones and Sudarshan Soma from Oracle.
It's API is very similar to PostgresNIO, this should make the adoption easier.
Most notable features:
- Standalone connections
- Connection pooling (backed by PostgresNIO's ConnectionPool module, thanks to @FabianFett)
- Database Resident Connection Pooling (DRCP)
- Multiple authentication options
- TLS support
- Oracle Cloud support
- Connection pinging
- SQL execution with binds (in and out)
- PL/SQL execution with binds (in, in/out and out)
- Commits and rollbacks
- LOB support (up to 1 GB)
There are a few more things I'd like to add before v1.0:
- Support for storing and reading JSON
- Support for storing and reading LOBs bigger than 1 GB per LOB (I'm unsure about the necessity of this)
- Removing the dependency on CryptoSwift (more about this below)
- mutual TLS support (optional)
- Improve documentation
Although I didn't publish a release yet, I'm already using the driver in production without issues (I'd encourage everyone else to wait for a release ).
Feedback is appreciated and breaking changes are still possible.
Usage example
import OracleNIO
import Logging
let logger = Logger(label: "my-logger")
let config = OracleConnection.Configuration(
host: "127.0.0.1",
port: 1521,
service: .serviceName("my_service"),
username: "my_username",
password: "my_password"
)
let connection = try await OracleConnection.connect(
configuration: config,
id: 1,
logger: logger
)
let id = 1
let username = "fancyuser"
let birthday = Date()
try await connection.query("""
INSERT INTO users (id, username, birthday) VALUES (\(id), \(username), \(birthday))
""",
logger: logger
)
let rows = try await connection.query("SELECT id, username, birthday FROM users", logger: logger)
for try await (id, username, birthday) in rows.decode((Int, String, Date).self) {
// do something with the rows.
}
try await connection.close()
Dependencies
- apple/swift-log
- apple/swift-nio
- apple/swift-nio-transport-services
- apple/swift-nio-ssl
- apple/swift-crypto
- vapor/postgres-nio (
_ConnectionPoolModule
) - krzyzanowskim/CryptoSwift (not part of SSWG)
I'd like to drop the dependency on CryptoSwift. It's currently used for CBC without padding and PBKDF2.
I've created a PR on swift-crypto which adds support for CBC without padding. It has been merged to main already. With the next release of swift-crypto, I'll be able to refactor the CBC related code to use it.
There is also a PR#98 on swift-crypto regarding PBKDF2, which is open since 2021. I'm wondering if I should add a C module for PBKDF2 until swift-crypto supports it, or stay on CryptoSwift. I'd like to hear some opinions on that.
I'm looking forward to your feedback