Zum Inhalt springen

Swift-Client

DuckDB verfügt über einen Swift-Client. Details finden Sie im Ankündigungsbeitrag.

DuckDB instanziieren

DuckDB unterstützt sowohl In-Memory- als auch persistente Datenbanken. Für eine In-Memory-Datenbank führen Sie aus:

let database = try Database(store: .inMemory)

Für eine persistente Datenbank führen Sie aus:

let database = try Database(store: .file(at: "test.db"))

Abfragen können über eine Datenbankverbindung gestellt werden.

let connection = try database.connect()

DuckDB unterstützt mehrere Verbindungen pro Datenbank.

Anwendungsbeispiel

Der Rest der Seite basiert auf dem Beispiel aus unserem Ankündigungsbeitrag, das Rohdaten aus dem NASA Exoplanet Archive verwendet und diese direkt in DuckDB lädt.

Einen anwendungsspezifischen Typ erstellen

Zuerst erstellen wir einen anwendungsspezifischen Typ, der unsere Datenbank und Verbindung aufnimmt und über den wir später unsere anwendungsspezifischen Abfragen definieren.

import DuckDB
final class ExoplanetStore {
let database: Database
let connection: Connection
init(database: Database, connection: Connection) {
self.database = database
self.connection = connection
}
}

Eine CSV-Datei laden

Wir laden die Daten aus dem NASA Exoplanet Archive:

wget https://exoplanetarchive.ipac.caltech.edu/TAP/sync?query=select+pl_name+,+disc_year+from+pscomppars&format=csv -O downloaded_exoplanets.csv

Sobald die CSV-Datei lokal heruntergeladen ist, können wir sie mit dem folgenden SQL-Befehl als neue Tabelle in DuckDB laden:

CREATE TABLE exoplanets AS
SELECT * FROM read_csv('downloaded_exoplanets.csv');

Das packen wir als neue asynchrone Factory-Methode in unseren Typ ExoplanetStore:

import DuckDB
import Foundation
final class ExoplanetStore {
// Factory method to create and prepare a new ExoplanetStore
static func create() async throws -> ExoplanetStore {
// Create our database and connection as described above
let database = try Database(store: .inMemory)
let connection = try database.connect()
// Download the CSV from the exoplanet archive
let (csvFileURL, _) = try await URLSession.shared.download(
from: URL(string: "https://exoplanetarchive.ipac.caltech.edu/TAP/sync?query=select+pl_name+,+disc_year+from+pscomppars&format=csv")!)
// Issue our first query to DuckDB
try connection.execute("""
CREATE TABLE exoplanets AS
SELECT * FROM read_csv('\(csvFileURL.path)');
""")
// Create our pre-populated ExoplanetStore instance
return ExoplanetStore(
database: database,
connection: connection
)
}
// Let's make the initializer we defined previously
// private. This prevents anyone accidentally instantiating
// the store without having pre-loaded our Exoplanet CSV
// into the database
private init(database: Database, connection: Connection) {
...
}
}

Die Datenbank abfragen

Das folgende Beispiel fragt DuckDB aus Swift über eine asynchrone Funktion ab. Dadurch wird der Aufrufer nicht blockiert, während die Abfrage ausgeführt wird. Anschließend wandeln wir die Ergebnis-Spalten mit der cast(to:)-Methodenfamilie von DuckDBs ResultSet in native Swift-Typen um und packen sie schließlich in einen DataFrame aus dem TabularData-Framework.

...
import TabularData
extension ExoplanetStore {
// Retrieves the number of exoplanets discovered by year
func groupedByDiscoveryYear() async throws -> DataFrame {
// Issue the query we described above
let result = try connection.query("""
SELECT disc_year, count(disc_year) AS Count
FROM exoplanets
GROUP BY disc_year
ORDER BY disc_year
""")
// Cast our DuckDB columns to their native Swift
// equivalent types
let discoveryYearColumn = result[0].cast(to: Int.self)
let countColumn = result[1].cast(to: Int.self)
// Use our DuckDB columns to instantiate TabularData
// columns and populate a TabularData DataFrame
return DataFrame(columns: [
TabularData.Column(discoveryYearColumn).eraseToAnyColumn(),
TabularData.Column(countColumn).eraseToAnyColumn(),
])
}
}

Vollständiges Projekt

Für das vollständige Beispielprojekt klonen Sie das DuckDB-Swift-Repository und öffnen Sie das ausführbare App-Projekt unter Examples/SwiftUI/ExoplanetExplorer.xcodeproj.